Compare commits

...

1985 Commits

Author SHA1 Message Date
SkyZeroZx c60c41e29a test(core): reduce fakeAsync usage in animation tests
Use async/await in animation acceptance tests and share the animation frame helper. Remove the obsolete fakeAsync frame utility and its Bazel dependency.
2026-09-13 14:20:24 -07:00
Kam fc2f6fd67d docs: stop the disabled aria toolbar radio group from changing selection
The disabled toolbar example marks its alignment radio group `disabled`.
Toolbars are soft-disabled by default, so the widgets only receive
`aria-disabled` and stay clickable, which the guide describes as focusable
but unavailable.

Since #70516 moved selection into the app, each radio also carries a
`(click)="alignment.set(...)"` handler that never checks the disabled state.
Clicking a disabled radio therefore changes the selection. Before that change
the radios had no app listener and the library ignored clicks on disabled
items.

Drop the three click handlers from the permanently disabled group in the
basic, material and retro variants, the same way the disabled redo button in
the same template already has none.
2026-09-11 16:00:02 -07:00
aparziale f2cf65a898 fix(vscode-extension): handle template literals when detecting supported decorator fields
The client decides whether a position in a TypeScript file belongs to a supported `@Component` field (`template`, `styles`, ...) with a lightweight `ts.Scanner` loop before forwarding requests to the language server and the HTML/CSS providers. `ts.Scanner#scan` doesn't handle template substitutions on its own: the `}` closing a `${...}` substitution is reported as a plain `CloseBraceToken` and the rest of the template literal is scanned as the start of a new one, swallowing everything up to the next backtick. As a result, once a template literal with substitutions appears in a file, every position after it is considered to be inside a template string, and TypeScript completions get polluted with HTML completions.

The scanner is now driven the same way the TypeScript parser does it, re-scanning the brace that closes a substitution as a `TemplateMiddle`/`TemplateTail` token.

In addition, the property assignment context previously only ended at a terminator found at the top level of the file, so it leaked from `template:` to every string literal that followed it inside the same decorator and class body. The context now ends at the first terminator found at the nesting depth where it was entered. Two kinds of strings were only recognized thanks to that leak, and only when declared after `template`: inline `styles` and the arguments of `@HostBinding`/`@HostListener` decorators, both of which the language service supports. They are now recognized explicitly, regardless of where they appear.

Fixes #65494
2026-09-11 15:19:01 -07:00
Shuaib Hasan Akib 467b37b4b4 docs(forms): document what required() considers empty
The `required()` validator treats `null`, `undefined`, `''`, `false` and `NaN` as empty, but the API
docs never defined "empty" at all and the validation guide listed only `null` and `''`.
2026-09-11 15:16:17 -07:00
Andrew Scott 2dcdf9aae6 fix(router): mark router_resource module-level symbols as side-effect free
Top-level Symbol() calls in router_resource.ts lacked /* @__PURE__ */
annotations, preventing bundlers like esbuild and Rollup from tree-shaking
the module and its dependencies when provideRouter() is used without
withRouterResources().

Fixes #70696
2026-09-11 14:40:05 -07:00
Kam c097c0144c docs: import bootstrapApplication from platform-browser in the CSP example
The `CSP_NONCE` example in the security guide imports `bootstrapApplication`
from `@angular/core`, which does not export it, so copying the snippet fails
with "has no exported member named 'bootstrapApplication'". It is exported from
`@angular/platform-browser`, which is where every other example in the docs
imports it from.

Keep `CSP_NONCE` on `@angular/core` and import `bootstrapApplication` from
`@angular/platform-browser`.
2026-09-11 13:12:29 -07:00
Joey Perrott 1b7dcc854a ci: stop passing preview gating inputs to adev preview build
The Googler check moved out of `pack-and-upload-artifact` and into the
pull request labeling action, which runs in a privileged
`pull_request_target` context where secrets are available. The build job
runs on `pull_request` and never receives secrets, so it no longer needs
`angular-robot-key` or `triggering-label`, and the `bypassed_for_forks`
placeholder can go away. Bumps the dev-infra pins to pick up that change.
2026-09-11 13:11:59 -07:00
Andrew Scott 2c6c67bee6 fix(router): maintain frozen state on rollback until resource loading completes
Previously, rollback recovery waited on hasValueOrResolved(), which checked whether the resource already had a value. This caused resources with values (e.g. defaultValue, existing values from prior navigations, or streamed emissions) to unfreeze prematurely while still in a loading state during rollback.

This change updates the rollback recovery check in the transactional snapshot effect to be solely determined by !source.isLoading().
2026-09-11 13:06:43 -07:00
Andrew Scott a8233232f5 fix(core): update FakeNavigation to match WHATWG HTML spec
Update FakeNavigation and Navigation API type definitions to match the
latest WHATWG HTML specification
(https://html.spec.whatwg.org/multipage/nav-history-apis.html):
- Add NavigationPrecommitController.addHandler() and support dynamic
  post-commit handler registration
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigationprecommitcontroller-addhandler).
- Include precommitHandler directly in NavigationInterceptOptions
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-intercept).
- Add hasUAVisualTransition and sourceElement properties to NavigateEvent
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-navigateevent-interface).
- Fix FakeNavigationHistoryEntry dispose event name from 'disposed' to 'dispose'
  and implement ondispose
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigationhistoryentry-ondispose).
- Implement Navigation.prototype.updateCurrentEntry
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigation-updatecurrententry).
- Implement Navigation.prototype.reload
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigation-reload)
  and share "performing a non-traverse navigation"
  (https://html.spec.whatwg.org/multipage/nav-history-apis.html#performing-a-non-traverse-navigation)
  logic with navigate().
- Implement standard event handler IDL properties (onnavigate,
  onnavigatesuccess, onnavigateerror, oncurrententrychange).
- Update internal specification comments and links from legacy PR draft URLs
  to official WHATWG multipage URLs.
2026-09-11 12:41:15 -07:00
Kam d0ed76c1d6 docs: fix the broken housing location template in the first-app tutorial
Step 11 of the first-app tutorial ships a `housing-location.ts` whose heading
reads `{{ housingLocatio()).name }}`, a misspelled property followed by an
extra parenthesis, so the step's source fails to compile with a template
parser error. Step 10 reuses this directory as its answer.

It came in with #61686, which migrated the tutorial to signal inputs. Use
`housingLocation().name`, matching the rest of the template and every other
step.
2026-09-11 10:59:36 -07:00
Kam 01d091bf9c fix(docs-infra): raise SSR fetch limit so the menubar guide prerenders
The aria menubar guide content is 2.9 MB, over the 2 MiB
maxResponseBodySize set in #69379. The fetch fails during prerender,
the navigation error handler redirects to /404, and the prerendered
page is saved as that redirect. Opening /guide/aria/menubar directly
or refreshing it lands on the 404 page.

Raise the limit to 4 MiB. The combobox guide was also within 27 KB of
the old limit.
2026-09-11 10:42:35 -07:00
Kam b9cbc5fbbe fix(docs-infra): match card grid row gap to column gap
The `:not(.docs-card-container) .docs-card` selector was meant to give
standalone cards a vertical margin, but no element has the
docs-card-container class, so it matched every card. Cards in a grid
without a header picked up the 1rem margin on top of the 1.25rem grid
gap, leaving rows 52px apart while columns are 20px apart (for example on
/reference/migrations, /guide/i18n and /roadmap).

Apply the margin only to cards that are not direct children of a card
grid.
2026-09-11 10:41:51 -07:00
Alan Agius 9918c81ca9 build: update @angular/ssr and add beasties dependency for adev and dev-app
In @angular/ssr 22.2.0-next.7, beasties was made an external dependency rather
than vendored internally. Because hoist: false is configured and preserveSymlinks
is enabled, rules_js does not hoist beasties into adev/node_modules and
dev-app/node_modules.

This commit adds beasties as an explicit dependency for both adev and dev-app
so that it can be resolved during bundling.
2026-09-11 10:40:29 -07:00
Angular Robot 11a66f254b docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-09-11 10:39:02 -07:00
Andrew Scott 37ca679192 Revert "fix(compiler): wrap @for collection expression before appending non-null assertion"
This reverts commit ed8f16c078.

This caused a breakage in TGP because the changes (correctly) produced new
diagnostics on ` @for (a of (x | async) || []; track a) {` x is `any`. This
results in `<any> | async` which produces `unknown | null` and then the `@if`
finally narrows this down to `{}` which isn't iteratable.
2026-09-11 10:05:15 -07:00
Matthieu Riegler ae33a5f55e test(core): fix view injector integration spec
Restore ChangeDetectionStrategy.OnPush that was removed in a previous commit, causing tests to fail due to ExpressionChangedAfterItHasBeenCheckedError.
2026-09-10 16:17:53 -07:00
Matthieu Riegler e2050759a4 docs: add error boundaries entries 2026-09-10 15:36:21 -07:00
Alan Agius 29f9dd5e77 refactor(devtools): update angular optimization plugin for JavaScriptTransformer API
Update createEsbuildAngularOptimizePlugin to use the new options object signature for JavaScriptTransformer.transformFile, and update the @angular/build dependency to 22.2.0-next.7.
2026-09-10 15:06:43 -07:00
Kam b9fb456971 docs(forms): close the unterminated code fences in the compatForm docs
Two of the three `compatForm` overloads open a fenced code block in their
`@example` and never close it. The fence then runs to the end of the tag, so the
API renderer emits a plain `<pre><code>` block for those two instead of a
highlighted one.

The result is that on the compatForm API page the first overload's example is
syntax highlighted while the other two, which contain identical code, render as
flat unstyled text.

Rebuilding //adev/src/assets:content with and without this change alters 1 of
1565 pages. That page goes from 6 highlighted and 2 plain code blocks to 8
highlighted and none plain.
2026-09-10 14:53:41 -07:00
Matthieu Riegler 9090a758be refactor(compiler-cli): relax nullish coalescing non nullable diagnostics on indexed access
When noUncheckedIndexedAccess is not enabled, indexed accesses do not include undefined in the type. This relaxes the check for nullish coalescing similarly to optional chaining. Fixes #70655

fixes #70655
2026-09-10 14:31:22 -07:00
SkyZeroZx 9e5ae4b710 test(core): remove redundant change detection configuration
OnPush is now the default change detection strategy, so the explicit test and example configuration is no longer needed.
2026-09-10 14:30:31 -07:00
SkyZeroZx 4380e683d8 docs(router): update scroll restoration example
Uses modern dependency injection and signal-based change detection in the custom scroll restoration example.
2026-09-10 14:30:31 -07:00
SkyZeroZx a958d7fe30 test(router): remove redundant change detection configuration
OnPush is now the default change detection strategy, so the explicit test configuration is no longer needed.
2026-09-10 14:30:31 -07:00
Angular Robot ceba448475 build: update pnpm/action-setup action to v6.1.0
See associated pull request for more information.
2026-09-10 14:29:47 -07:00
Kam 9073469416 fix(docs-infra): escape the code example header
`buildHeaderElement` interpolated the header into a string that is then parsed
as HTML, so markup in a header became an element instead of text. The ten
captions on https://angular.dev/guide/i18n/translation-files read
`messages.fr.xlf ()`, having turned `(<trans-unit>)` into an empty element.

These are the only two headers in the guides containing markup.
2026-09-10 14:29:10 -07:00
Kam 61b353ebee fix(docs-infra): restore the xlf regions on the i18n guides
#65848 renamed `messages.fr.xlf.html` to `messages.fr.xlf` and, in the same
lines, reverted `region=` back to `visibleRegion=`, undoing #65530 from two
weeks earlier. `visibleRegion` is not read by the tokenizer, and `xlf` is not
in `REGION_MATCHERS`, so both halves of the snippet handling broke at once.

Since then https://angular.dev/guide/i18n/translation-files has shown the same
78 line file ten times where the prose describes single `<trans-unit>`
elements, and https://angular.dev/guide/i18n/manage-marked-text three times,
each carrying the `#docregion` scaffolding into the rendered code.

Mapping `xlf` to the html matcher also cleans up
https://angular.dev/guide/i18n/example, which renders the whole file on purpose
but leaked 27 marker lines into it.

`docs-code.spec.mts` already loads this fixture but only asserted the block
existed, so it stayed green throughout. It now also asserts no marker survives.
2026-09-10 14:29:10 -07:00
Andrew Scott 14dbbf9b68 fix(compiler): wrap @for collection expression before appending non-null assertion
When generating type check blocks for `@for` loops, a non-null assertion is appended to the collection expression. If the collection expression is a compound expression (e.g. binary or logical operations like a && b), the lack of outer parentheses caused the ! to bind only to the rightmost operand (a && b!), leading to typecheck errors such as TS2532.

This wraps the expression via .wrapForTypeChecker() before appending !.
2026-09-10 13:22:52 -07:00
Angular Robot 4b3f8c224b docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-09-10 11:15:04 -07:00
Doug Parker 8ca879e2d8 refactor(forms): expose consequentialHint annotation
Unlike `readOnlyHint` and `untrustedContentHint`, Angular cannot infer any reasonable default value for `consequentialHint` and simply exposes it to users to specify as appropriate.

See: https://groups.google.com/a/chromium.org/g/chrome-ai-dev-preview/c/uHu5kfclbKw/m/dgorjfHPDgAJ
2026-09-10 09:50:14 -07:00
Doug Parker 96dbae53bb refactor(core): expose consequentialHint annotation
This allows `consequentialHint` to be passed to `ModelContext.registerTool`. From Angular's perspective, this is simply a pass-through option.

See: https://groups.google.com/a/chromium.org/g/chrome-ai-dev-preview/c/uHu5kfclbKw/m/dgorjfHPDgAJ
2026-09-10 09:50:14 -07:00
Alan Agius f557ead292 build: add @modelcontextprotocol/server devDependency and vendor license
Add @modelcontextprotocol/server to devDependencies in @angular/core to extract its LICENSE file via a genrule in the third_party directory, and remove the previously checked-in package.json.
2026-09-10 09:49:08 -07:00
Alan Agius 593a5df61c build: make webmcp-types sources genrule cross-platform
Replace `sed -i` in-place substitution with direct stdout redirection from the source file to destination outputs. `sed -i` behaves differently between GNU and BSD sed, which caused build failures on macOS.
2026-09-10 09:49:08 -07:00
Kam 8576f161ae fix(docs-infra): highlight home page code for the resolved theme
`CodeBlock` picked `github-light` only when the theme was exactly `light`, but
`Theme` also has `auto`, the value for anyone who has not opened the theme
menu, and `theme()` is `null` during prerendering. Both fell to `github-dark`,
so the samples in the Signals, Control Flow and Deferrable Views tabs on
https://angular.dev rendered on a dark slab inside a light page.

Resolve the theme in `ThemeManager`, which already owns the `auto` translation.
`resolvedTheme` returns `light` when `theme()` is `null`, which happens only
during prerendering, so `window` is never read. The device scheme moves into a
signal so `auto` also reacts to OS scheme changes.
2026-09-09 22:27:24 +02:00
SkyZeroZx 947f3ffaef test(core): reduce fakeAsync usage in tests
Use async/await where needed. Remove unused dependencies.
2026-09-09 22:26:29 +02:00
Edu cea6896a0f fix(core): return null when getDirectiveMetadata is called with null or undefined
Safely return null instead of throwing an unhandled TypeError when getDirectiveMetadata is called with a falsy directive or component instance.
2026-09-09 22:26:00 +02:00
Edu ef09d108f2 fix(devtools): safely handle foreign root elements in feature detection
Prevent Angular DevTools from crashing when elements matching [ng-version] in the DOM do not belong to the host application (such as third-party custom elements or browser extensions). ng.getComponent returns null for these elements, which previously caused ng.getDirectiveMetadata to throw.
2026-09-09 22:26:00 +02:00
Kristiyan Kostadinov a410e1370c release: cut the v22.2.0-next.7 release 2026-09-09 22:22:24 +02:00
Kristiyan Kostadinov 0625c1d81d release: cut the v22.2.0-next.6 release 2026-09-09 22:16:04 +02:00
Kristiyan Kostadinov 2f3afc9909 docs: release notes for the v22.1.6 release 2026-09-09 22:12:02 +02:00
Kristiyan Kostadinov 018bec1ecc docs: release notes for the v20.3.31 release 2026-09-09 22:02:37 +02:00
Kristiyan Kostadinov c62641fdb0 docs: release notes for the v21.2.23 release 2026-09-09 21:55:18 +02:00
Kristiyan Kostadinov b6517a6672 build: resolve pnpm 12 breakages
Accounts for breaking changes in pnpm 12.
2026-09-09 21:48:04 +02:00
Andrew Scott 679c50dcbe refactor(router): Remove ActivatedRouteSnapshot from resourceContext
providing the snapshot is a bit incompatible with how things are meant to work here.
The snapshot is only accurate during the setup and would be out of date
on followup navigations
2026-09-09 18:09:11 +02:00
Kristiyan Kostadinov 25228d0cc3 test: fix failing boundary test
Fixes a test that's breaking CI.
2026-09-09 17:23:07 +02:00
Angular Robot 2c71e8823a docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-09-09 16:35:02 +02:00
Angular Robot 25317c3837 build: update dependency cypress to v16
See associated pull request for more information.
2026-09-09 16:33:56 +02:00
Angular Robot bc0fd20d55 build: update dependency vitest to v5
See associated pull request for more information.
2026-09-09 16:31:33 +02:00
Angular Robot 8414f90a6f build: update cross-repo angular dependencies
See associated pull request for more information.
2026-09-09 16:30:15 +02:00
Alan Agius bc3a6cda5d fix(platform-server): avoid sourcemap corruption during domino path substitution
The substitution regex `\./(.+)/third_party/domino/bundled-domino` was used to rewrite the relative execroot path emitted by Rollup for the domino external import into `../third_party/domino/bundled-domino.mjs`.

However, `ng_package` runs `text_replace` across all generated package files, including `.map` files which are serialized on a single line. The `\./` pattern unintentionally matched the `./` inside `"../../"` in the `sources` array, and the greedy `.+` wildcard matched across the rest of `sources` and the `"sourcesContent": [` declaration up to the domino import within the first source file's content. This corrupted `init.mjs.map` and `_server-chunk.mjs.map` by destroying `sourcesContent` and populating `sources` with raw file contents.

This commit updates the substitution regex to use a negative lookbehind `(?<!\.)` to prevent matching `../` sequences, and restricts the path characters to valid filesystem path characters `[a-zA-Z0-9_./-]+` rather than `.+`.

Fixes #70625
2026-09-09 16:27:18 +02:00
Angular Robot 199da47d58 build: update dependency node to v24.21.0
See associated pull request for more information.
2026-09-09 16:26:45 +02:00
Kam d0a748cc1b docs(animations): stop the query() usage notes truncating at a code sample
The `query()` usage notes contain this code sample:

    query(':self, .record:enter, .record:leave, @subTrigger', [...])

TypeScript's JSDoc parser treats whitespace followed by `@subTrigger` as the
start of a new tag, even inside a fenced code block. The extraction ends up with
a 145 character `@usageNotes` cut off mid-sample and a phantom `@subTrigger` tag
holding the remaining 2453 characters, which the renderer discards.

The result is that https://angular.dev/api/animations/query ends mid-line inside
that code block. The "Entering and Leaving Elements" and "Usage Example"
sections never render, and the two links pointing at the first of them, one in
the same JSDoc and one in guide/animations/complex-sequences, both dead-end.

Move the `@` token to the front of the selector so it follows a quote rather
than a space. Order within a comma separated selector list is irrelevant, and
the sample's own prose describes it as a set of tokens merged into one string.

The rendered page grows from 7109 to 21269 bytes and gains the
`entering-and-leaving-elements` and `usage-example` anchors. Rebuilding
//adev/src/assets:content with and without the change alters 1 of 1565 pages.
2026-09-09 16:26:08 +02:00
Andrew Scott 094bce9e3d fix(router): determine blocking state solely by resource loading status
Previously, blocking router resources waited on hasValueOrResolved(), which checked whether the resource already had a value. This caused blocking resources with initial values (e.g. defaultValue), streamed early emissions, or existing values during route reloads to resolve prematurely while still in a loading state.

This change updates the blocking resolution check to be solely determined by !underlyingRes.isLoading().
2026-09-09 16:25:24 +02:00
Jaime Burgos 8afd85c6d7 test(forms): migrate integration tests to zoneless scheduling
Use whenStable instead of manual change detection so integration tests exercise scheduled rendering. Await asynchronous callbacks and remove redundant timer waits to keep assertions within the test lifecycle.
2026-09-09 16:24:37 +02:00
Kristiyan Kostadinov 9b80d4ce9e fix(compiler): namespace @property declarations
The `@property` atrule allows users to define custom CSS variables. These changes update the compiler to account for when namespacing variables.
2026-09-09 16:23:57 +02:00
SkyZeroZx 9021e275d1 docs: use code block headers for filenames
Move filename comments into headers to keep examples focused on code.
2026-09-09 16:23:09 +02:00
Kam 8037e4ac08 docs(docs-infra): correct stale paths and routes in the tutorials README
The tutorials README documents how tutorial content, routes and the shared
common project are laid out, and several of those statements no longer match
the pipeline.

Links: eight links were written as `/src/content/...`. GitHub rewrites a
root-relative markdown link to `/<owner>/<repo>/blob/<branch>/<path>`, so they
resolved to `angular/angular/blob/main/src/content/...` and returned 404. They
now use the repo-root path, matching the convention already used in
`adev/src/app/editor/README.md`.

Routes: the step examples claimed the number prefix is dropped, giving
`/tutorials/learn-angular/components-in-angular`. `routes.mts` emits the step
directory name verbatim and uses the number only for ordering, and the
production sitemap lists only the numbered form, so the two examples and the
bullet describing the step URL are corrected.

Common project: `adev/src/content/tutorials/common` was removed in #53511 and
the shared project now lives in `adev/shared-docs/pipeline/tutorials/common`.
The section also documents the per-tutorial `common` directory that
`tutorial_index.mts` applies on top of the shared one, and drops the reference
to `app.module.ts`, which the standalone common project does not have.

Update dependencies: the script covered five of the eight projects that carry
a package-lock.json. `signals/common`, `signal-forms/common` and the shared
common are added; all eight are already updated together by lock file
maintenance.

The README is excluded from `generate_guides`, so no rendered page changes.
Building `//adev/src/content/tutorials/...` with and without this change
produces byte-identical output across all 213 generated files.
2026-09-09 16:22:32 +02:00
Shuaib Hasan Akib f53b3b6e95 docs: add CommonModule guidance to AI best practices
Clarifies that CommonModule should not be imported wholesale when narrower imports can be used instead.
2026-09-09 16:21:53 +02:00
Kam 4043800ef2 fix(docs-infra): recognise an alert that follows prose in the same paragraph
`docs-alert` was the only marked extension in the pipeline without a `start`
hook, so marked never cut `inlineText` short at an alert and swallowed any
directive that was not at the start of the inline source. Writing the alert on
its own line without a blank line before it left the literal text in the body.

On https://angular.dev/guide/http/testing two alerts render as boxes and a
third shows as `IMPORTANT:` in the paragraph text. Also affects
https://angular.dev/errors/NG3003 and the first step of the first app tutorial.

The same renderer handles JSDoc, so one API page changes too:
https://angular.dev/api/upgrade/static/downgradeModule has three `NOTE:`
continuation lines inside bullets that now render as alerts.

`docs-video` and `docs-pill` already declare `start` the same way.
2026-09-09 16:21:14 +02:00
Kam d3ccf5ca82 docs: fix the visibleLines range on the ngFor tutorial step
`visibleLines="26-131"` is not valid JSON, so `expandRangeStringValues` threw
and returned an empty list. The rendered attribute was empty, and the viewer
treats that as no range at all, so no ExampleViewer was created:
https://angular.dev/tutorials/first-app/08-ngFor showed all 128 lines of
`home.ts` with no collapse and no expand control, including the `@for` block
the reader has not written yet.

The file is 128 lines and the property this step adds ends at 127. The sibling
snippet on the same page already uses the `[start,end]` form.
2026-09-09 16:20:10 +02:00
Angular Robot a959ceda76 build: update pnpm to v12
See associated pull request for more information.
2026-09-09 16:19:17 +02:00
Kam 93f17e0bdf docs: fix the docregion marker in the apache config example
The marker was written `# docregion`, but the hash matcher expects
`# #docregion`, one hash for the comment and one for the marker. It was not
recognised, so it was never stripped and rendered as the first line of the
Apache config on https://angular.dev/guide/i18n/deploy.

The sibling `nginx.conf`, shown on the same page, already has the correct form.
2026-09-09 16:18:39 +02:00
Shuaib Hasan Akib e80c91b262 docs: render the unsupported version range as an alert 2026-09-09 16:17:46 +02:00
Shuaib Hasan Akib 1bc7e3c2c3 refactor(core): use native Promise.withResolvers() in remaining tests
Replaces the remaining hand-rolled deferred promise implementations
with the native `Promise.withResolvers()` API and removes the now
unused helper and import.

Follow-up to #69739.
2026-09-09 16:17:04 +02:00
SkyZeroZx 49a797f510 test(core): remove redundant change detection configuration
OnPush is now the default change detection strategy, so the explicit test configuration is no longer needed.

Updates outdated Bazel test targets to use the zoneless configuration.
2026-09-09 16:16:28 +02:00
Kam b7d432794e fix(docs-infra): keep an explicit theme choice when the OS scheme changes
`watchPreferredColorScheme` applied the OS scheme unconditionally, while
`setTheme`, `loadThemePreference` and the bootstrap script in index.html all
only follow it for `auto`. Choosing Light and then letting the OS switch to
dark repainted the site dark while the theme menu still reported Light, until
a reload restored it.
2026-09-09 16:15:52 +02:00
Kam b0cda277da refactor(docs-infra): validate api/cdk and api/aria links
`isKnownRoute` exempted both families behind TODOs waiting on route extraction
for those packages. That extraction had already landed when the TODOs were
written in #66254: cdk pages since #60853 and aria pages since the cross-repo
workflow. `defined-routes.json` carries 70 `api/cdk` and 39 `api/aria` routes
today, and all 45 such link targets in the guides resolve, so the build stays
green without the exemptions.

The gap was not theoretical. `guide/aria/select.md` and
`guide/aria/multiselect.md` linked `api/cdk/overlay/CdkConnectedOverlay`, which
has never been a route, and it shipped as a 404 for six months. Link validation
landed four months into that and said nothing, because of this exemption. It
took a user filing #68914 and an outside contributor fixing it in #68915.

Pointing an existing `api/cdk` link at a symbol that does not exist passes the
build today and fails it with this change.
2026-09-09 16:15:14 +02:00
Kam d3b0bb1d8c test(docs-infra): run the orphaned shared-docs pipes specs
`relative-link.pipe.spec.ts` and `is-active-navigation-item.pipe.spec.ts`
arrived with this package's BUILD file in #57132, but no test target came with
them and `lib` excludes `**/*.spec.ts`, so nothing has ever compiled them.
`bazel query` reports both as not declared in the package.

They pass unmodified. `getRelativeUrl` has no other coverage in the repo, and
both pipes are used by the search dialog, the navigation list and the not
found page.
2026-09-09 16:14:23 +02:00
SkyZeroZx c235ecef8a test(forms): remove redundant change detection configuration
OnPush is now the default change detection strategy, and tests run zoneless by default, so the explicit configuration is no longer needed.
2026-09-09 16:13:08 +02:00
Kam 0bdbbcf4a8 fix(docs-infra): only read a deprecation version from the start of the tag
`getTagSinceVersion` matched `\d+(\.\d+)?` anywhere in the tag comment. That
works for `@developerPreview`, `@experimental` and `@stable`, whose comment is
only a version, but `@deprecated` also carries a message, so any number in the
prose won. https://angular.dev/api/common/getLocaleCurrencyCode reads
"deprecated since v4217", taken from "a map of locale to ISO 4217 currency
codes", and eighteen sibling pages take v18 from the "i18n" in "relying on the
`Intl` API for i18n".

Anchoring the match, and allowing the `since`/`from`/`as of` prefixes the
comments use, leaves all seventy-nine correctly versioned comments untouched.
`generate_manifest` carries its own copy of the regex, so the API list badges
had the same values.

Those `@angular/common` comments never stated a version, so they now say `18.0`
explicitly, the release `d34c033902` (#54483) first shipped in, matching the
`@deprecated 18.0` already on `FormatWidth` in the same file. Nine tags in that
file had no version at all and were showing no badge; they are from the same
commit and now say `18.0` too.
2026-09-09 16:12:18 +02:00
Kristiyan Kostadinov 77e2a2a85c refactor(core): expose onDestroy in DirectiveFixture
Exposes the `onDestroy` method from the host component in `DirectiveFixture`. We need this for harnesses in the CDK.
2026-09-09 16:11:33 +02:00
Kam d6d51a0ef8 test(devtools): run the orphaned app component spec
`app.component.spec.ts` has been in the tree since the initial DevTools commit
in 2020, but no revision of `shell-browser/src/app/BUILD.bazel` has ever listed
it, and that file has no globs. Two of the three specs in the directory are
wired up; this one has never run.

It could not run as written. The setup declared `AppComponent` and imported
`RouterModule.forRoot([])`, neither of which applies now that the component is
standalone and injects `MessageBus` and `DEEP_LINK_INSTANCE_ID`.

It now stubs the `chrome.devtools` surface that `ngOnInit` reads and covers
both lifecycle hooks: the listeners registered on init, the two performance
track emits, the three guards on the deep link listener, and the listeners
removed on destroy.

Follow-up to #70570, which fixed the same problem in ng-devtools-backend.
2026-09-09 16:11:01 +02:00
hawkgs 635ef1bd80 refactor(devtools): contain hydration overlays functionality on the be
Move the refresh mechanism of the hydration overlays to the backend,
delegating only the feature toggling to the frontend.
2026-09-09 16:10:25 +02:00
Kam 0029c3ba5a docs: use a supported alert level for the cross-field validation note
`WARNING:` is not an `AlertSeverityLevel`, so the paragraph rendered as plain
body text on https://angular.dev/guide/forms/signals/cross-field-logic while
the three other alerts on the page rendered normally. `CRITICAL` is the level
kitchen-sink.md defines for warning the reader off a footgun.

The five `@Component({/* ... */})` collapses are the formatter's. The file has
drifted out of prettier since it landed, and `ng-dev format changed --check`
checks whole changed files.
2026-09-09 16:09:49 +02:00
SkyZeroZx 5afdd98de1 fix(docs-infra): remove space after decorator symbol
Handle the separate whitespace token emitted by Shiki when a decorator name is linked to its API reference.
2026-09-09 15:59:01 +02:00
arturovt bd9b45b5cc feat(core): allow reading Injector from a view or content query
Queries could already read `ElementRef`, `TemplateRef` and
`ViewContainerRef` from a matched node via the `read` option, but not the
node injector. Getting it required a helper directive on the element.

`{read: Injector}` now returns the node injector of the matched element,
so a component can resolve tokens as they are seen from that element. This
is useful when wrapping third-party components that project templates and
expect directives inside those templates to inject the host component.

Works for `@ViewChild`/`@ContentChild` and the signal-based
`viewChild`/`contentChild`.

Fixes #47760
2026-09-09 15:57:32 +02:00
Matthieu Riegler d470afa8b2 refactor(platform-server): ensure error boundaries work with ssr/hydration (#70463)
Added some tests to ensure error boundaries work with SSR and hydration.

PR Close #70463
2026-09-09 15:56:05 +02:00
Alex Rickabaugh f4a5650ed9 feat(language-service): add support for @boundary blocks (#70463)
Add support for the new `@boundary` and `@error` control flow blocks in the Angular Language Service.

This includes:
- Updating outlining spans to handle boundary blocks correctly.
- Adding classification visitor methods for semantic tokens.
- Adding template target visitor methods for navigation and hover support.
- Updating the TextMate grammar to recognize `@boundary` and the `when` clause.

PR Close #70463
2026-09-09 15:56:05 +02:00
Alex Rickabaugh f7597cb7d9 refactor(compiler): template type-checking support for @boundary (#70463)
Add support for `@boundary` blocks in the template type-checking pipeline.

PR Close #70463
2026-09-09 15:56:05 +02:00
Alex Rickabaugh 54ed62d240 refactor(core): implement @boundary runtime primitives and AST nodes (#70463)
Add the runtime primitives `ɵɵboundaryCreate` and `ɵɵboundaryUpdate` to
the core instructions, which handle synchronous view destruction and
provide the `ON_ERROR` interceptor hooks.

Also include the initial compiler AST representations for the new syntax
including the Lexer tokenization and HTML Parser integration. This lays
the foundational structure for `@boundary` prior to code generation.

Co-authored-by: Matthieu Riegler <kyro38@gmail.com>

PR Close #70463
2026-09-09 15:56:05 +02:00
Alex Rickabaugh f6afb807c1 feat(core): add ErrorBoundary programmatic APIs (#70463)
Implement error interception during refreshView and provide onError callback options in ViewContainerRef for programmatic rendering and encapsulation of boundary errors.

PR Close #70463
2026-09-09 15:56:05 +02:00
Matthieu Riegler f0a271c7bd fix(compiler-cli): do not flag callable objects with zero parameters in uninvoked track function check
In `@for` blocks, tracking callable objects by reference (e.g. signal forms `FieldTree`, signals, or custom callable objects) is a valid pattern when tracking by object identity. Previously, `UninvokedTrackFunctionCheck` (NG8115) flagged any property read whose type has call signatures, regardless of whether the target was an actual track function expecting arguments or a method reference.

This commit updates `UninvokedTrackFunctionCheck` to only emit a diagnostic when the target expression has call signatures that declare parameters (functions/methods expecting arguments like `(item)` or `(index, item)`) or is a method declaration. Callable objects without parameters accessed as properties are now recognized as tracked values and not flagged as uninvoked track functions.

Fixes #70207
2026-09-09 15:54:09 +02:00
arturovt 8227e5cf6d fix(router): keep detached route subtree contexts isolated and intact
When a route is detached for `RouteReuseStrategy`, its component and child
`RouterOutlet`s stay alive and keep referencing the `ChildrenOutletContexts`
they were created with. `detachAndStoreRouteSubtree` used to call
`onOutletDeactivated()`, which swaps that object's Map for an empty one, so
after re-attaching, the inner outlet and the router read from two different
context trees and deeper child routes (e.g. an `edit` route under a reused
list) never rendered.

Now, on detach: take the child contexts map as-is (destruction still calls
`onOutletDeactivated()` to prune) and give the `OutletContext` a fresh
`ChildrenOutletContexts`. This keeps the detached component rendering from
its stored map once re-attached, and prevents whatever activates next in
the same parent outlet (e.g. a sibling tab) from mutating or wiping that
stored map.

Fixes #57285
2026-09-09 15:53:28 +02:00
Angular Robot 9a58353b1b build: update cross-repo angular dependencies
See associated pull request for more information.
2026-09-04 07:52:21 -07:00
SkyZeroZx 063eda2db2 test(core): replace act with actAsync
Replaces the custom `act` helper function with the standardized `actAsync` utility
2026-09-04 07:48:11 -07:00
SkyZeroZx 318fefad30 test(forms): Add utility functions and update test files to use them
Moves common helper functions into a shared test utility to reduce duplication.
2026-09-04 07:48:11 -07:00
Kam 3dfc855381 test(devtools): run the orphaned supported-apis spec
`supported-apis.spec.ts` was added in #60585, in a commit that also edited the
`ts_test_library` three lines below the `srcs` it was left out of. No revision
of that BUILD file has ever listed it, so it has not run since March 2025. The
target goes from 12 specs to 14.

Wiring it up alone would not have worked. Every `*IsSupported` helper calls
`ngDebugClient()`, which throws when `window.ng` is undefined, and the old
`expect(supported).toBeTruthy()` set no `ng` at all. It now stubs `ng` and
checks the flag set and that each flag tracks its own debug API.

`ng-debug-api.spec.ts` adds an `[ng-version]` root and did not remove it, which
`getAppRoots()` then picks up in the other file under jasmine's random
ordering, so it now clears the DOM in its own `afterEach`.

`glob` matches the sibling `directive-forest/component-tree` target and keeps
the next spec in this directory from being dropped the same way.
2026-09-04 07:46:46 -07:00
Kam 3481b15167 docs: correct filename labels on code examples
Four labels name a different file than the block loads: three tabs on the
animations guide say `leave.*` but load `leave-parent.*` (`leave.*` is a
separate example shown earlier on the page), and one block in the reactive
forms section says `actor-form-template.component.html` but loads
`actor-form-reactive.component.html`.

The other three leak the `.1`/`.2` variant suffix, which every other
numbered-variant header in adev strips.

https://angular.dev/guide/animations
https://angular.dev/guide/legacy-animations/reusable-animations
https://angular.dev/guide/forms/form-validation
2026-09-04 07:46:12 -07:00
Lazizbek Ergashev 70756b506c fix(core): apply SkipSelf to only the starting node in embedded views
The node-by-node walk used to resolve a token through an embedded view
injector forces the `Self` flag on every node injector lookup. Combined
with `SkipSelf`, that lookup can never match, so every node between the
injection point and the view boundary was skipped and the token was
resolved from the custom injector instead of the nearest parent node.

Clear `SkipSelf` once the starting node has been checked, so only that
node is skipped. This also makes the strip at the embedded view injector
redundant.

Fixes #70547
2026-09-04 07:43:55 -07:00
Angular Robot bae170d535 build: update bazel dependencies
See associated pull request for more information.
2026-09-04 07:27:27 -07:00
Kam 26afa313f3 fix(docs-infra): correct example viewer tab state and line numbering
Five more defects in the example viewer, following #70508.

The DOM was queried before Angular rendered it. `setCodeLinesVisibility()`
walks the rendered lines but ran synchronously on tab change, so it measured
the outgoing tab and the incoming file showed in full. The selected tab was
also lost when the code block was hidden and reshown, because the recreated
tab group had no `[selectedIndex]` while `snippetCode` survived, leaving the
strip and the code disagreeing.

`expandable` was computed once at startup by counting hidden DOM nodes, so a
collapsed tab offered no way to expand it, and recomputing that count on tab
change would drop the control whenever the block was expanded, since nothing
is hidden then. Both paths now share one rule: a file is expandable when it
has a `visibleLinesRange` and either the block is expanded or the range
actually hides lines, so a range that covers its whole file still gets no
inert control.

Array indices were also mixed with 1-based line numbers: the gap check tested
`index - 1` for the preceding line, drawing a `...` separator inside
contiguous ranges, and the gutter tested `index` while the code tested
`index + 1`, shifting every line number by one.

Five new specs cover these, using the comma-separated range format the
pipeline emits; each fails with its fix reverted. The tab label also moves
from 0.8125rem to 0.875rem to match the code beside it.
2026-09-04 07:26:24 -07:00
Andrew Scott 74c1716cef refactor(compiler-cli): index pipes in template expressions
Update the template indexer to discover and record pipes used in template expressions.

This associates template pipe identifiers with their target pipe class declarations, enabling indexers and language tooling to properly resolve and cross-reference pipes.
2026-09-04 07:13:50 -07:00
Andrew Scott 3064f3f1dc feat(router): expose router resources in public API
Router resources integrate the Angular router with the Signals Resource API, allowing route-level data fetching during navigation transitions.
2026-09-04 07:10:49 -07:00
Andrew Scott caeab598c9 refactor(compiler): emit any as type argument for ɵɵInjectableDeclaration
The static `ɵprov` field emitted on `@Injectable()` classes uses `ɵɵInjectableDeclaration<T>`.
When a subclass extends a generic `@Injectable()` base class with contravariant parameters
(such as callback/transformer methods depending on generic type parameters), TypeScript's
static side inheritance check (`typeof Sub extends typeof Super`) fails with `TS2417` because
`ɵɵInjectableDeclaration<Sub>` is not assignable to `ɵɵInjectableDeclaration<Super<any>>`.

Using `any` (`o.DYNAMIC_TYPE`) in `createInjectableType` avoids strict variance checks on
static inheritance for internal Ivy definitions and aligns with other Ivy declaration types.
2026-09-04 07:05:23 -07:00
Angular Robot 98960556a6 build: update mcp-b webmcp dependencies to v5
See associated pull request for more information.
2026-09-04 07:04:49 -07:00
Matthew Beck 81c3f3a6aa release: cut the v22.2.0-next.5 release 2026-09-02 19:40:50 -07:00
Matthew Beck e4b8822c43 docs: release notes for the v22.1.5 release 2026-09-02 19:37:23 -07:00
Matthew Beck 502fa130aa fix(docs-infra): ignore external links when mapping navigation items to routes
When navigation items contain external URLs (e.g. https:// links for documentation or third-party resources), mapNavigationItemsToRoutes previously registered them as Angular Router route definitions. In recent versions of @angular/build, the static prerender worker asserts that discovered routes do not return empty content during SSG prerendering, causing production builds and CI adev-deploy to fail on these routes.

This change filters out external links in mapNavigationItemsToRoutes so only valid internal application paths are registered as Angular routes.
2026-09-02 19:07:15 -07:00
SkyZeroZx 69c87301aa fix(vscode-extension): prevent JSDoc link provider injection
Treat link targets as file paths so crafted documentation cannot select arbitrary VS Code resource providers.

Fixes https://github.com/angular/angular/issues/70512
2026-09-02 16:06:55 -07:00
arturovt 58d536bc83 fix(core): don't fail NgModule checks for a pipe that extends a base class
When an abstract base class has something like a lifecycle hook, Angular
compiles it as a directive with no selector. If a pipe extends that base
class, the pipe picks up the base class's directive definition through
normal class inheritance.

The NgModule dev-mode checks then got confused by that inherited
definition and reported the pipe as a broken directive:

  - "Directive SomePipe has no selector, please add it!"
  - or, if the base class was a default (standalone) abstract directive,
    "SomePipe is marked as standalone and can't be declared..."

Both only happened in tests (TestBed), not when running the app.

Now the selector check and the standalone check both look at the pipe's
own definition and ignore a directive definition that only came from a
base class.

Fixes #36427
2026-09-02 16:06:12 -07:00
SkyZeroZx 7168bed663 fix(core): validate SVG animation attributes outside the SVG namespace
Make the SVG animation security context depend on the tag name instead of the namespace the element was created in. An animation element declared outside an `<svg>` is created in the HTML namespace, but still animates once it ends up inside an SVG subtree, so to and `attributeName` bindings were reaching the DOM unvalidated.

Fixes  #70490
2026-09-02 16:05:47 -07:00
Andrew Scott 7137a41223 feat(router): stabilize auto cleanup injectors feature
Removes experimental tags and stabilizes withAutoCleanupInjectors, AutoCleanupInjectorsFeature,
and RouteReuseStrategy cleanup methods, while re-exporting withExperimentalAutoCleanupInjectors as deprecated.
2026-09-02 16:05:12 -07:00
Jaime Burgos af26a8c521 fix(router): avoid view transitions when the user agent provides one
Preserve hasUAVisualTransition through Location and the Router navigation pipeline. This prevents withViewTransitions from starting an author transition after the browser has already performed one, including across redirects and when using experimental platform navigation.
2026-09-02 16:04:41 -07:00
Andrew Scott cd771174b9 build(zone.js): fix release PR URL and filter changelog to zone.js scope
In recent conventional-changelog version updates, the underlying
@conventional-changelog/git-client dropped support for the raw `grep` and
`extendedRegexp` options, causing all monorepo commits to be included in the
zone.js changelog. Additionally, without `tagPrefix: 'zone.js-'`, conventional-changelog
treated monorepo release tags as release boundaries, generating changelog sections
for every intermediate monorepo release.

This change:
- Configures `tagPrefix: 'zone.js-'` and filters commits by `scope === 'zone.js'`
  via `writerOpts.transform` in the gulp changelog task.
- Fixes the PR creation link in the release script to use the cross-fork
  compare URL format on GitHub.
- Fixes the release commit SHA lookup in `cutReleaseWorkflow`.
- Updates zone.js release documentation.
2026-09-02 15:59:31 -07:00
Angular Robot a66fd64cd4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-09-02 15:52:44 -07:00
Angular Robot de91d10b80 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-09-02 15:39:44 -07:00
Cheng-Hsuan Tsai d7af4b5aca docs: decouple selection from aria toolbar examples and guide 2026-09-02 15:14:21 -07:00
Kam 45148dae44 docs: correct openFiles entries that point at missing files
Two tutorial steps list a file in `openFiles` that does not exist, and a
missing entry is dropped without complaint. `first-app/05-inputs` asks for
`housinglocations.ts` when the file is `housinglocation.ts`; since
`hiddenFiles` is everything not in `openFiles`, the interface that step
teaches was marked hidden rather than opened.
`signals/5-component-communication-with-signals` asks for
`quantity-selector.ts`, which exists in neither `src` nor `answer`. Every
openFiles entry in the tutorials now resolves.
2026-09-02 14:32:45 -07:00
Kam 90b9e081f5 fix(docs-infra): keep the collapsed code state when a code block is reshown
The code block lives inside `@if (showCode())`, so hiding it destroys the DOM and
showing it builds a fresh copy with no hidden lines. Nothing reapplied
`setCodeLinesVisibility()`, so a collapsed block came back showing the whole file.

Reapply it once the block is rendered again. It already branches on `expanded()`,
so a block that was expanded stays expanded.
2026-09-02 14:32:17 -07:00
Kam 431b170fd5 build: narrow the preview exclusions for two example apps
`reactive-forms` and `form-validation` were excluded from `embeddable` in
full, with a TODO to fix them. The examples are fine; four partial snapshots
quoted by the guides are not, since each shares the final template of the
component it precedes, which references members it does not have yet.
Excluding those four files clears all 30 errors and puts 23 app files back in
the preview pool, so both guides' final components can be previewed for the
first time.
2026-09-02 14:30:50 -07:00
Angular Robot 6fdb7f061b build: update dependency mocha to v12
See associated pull request for more information.
2026-09-02 14:30:09 -07:00
Angular Robot b8a750fb34 build: update dependency bazel to v8.8.0
See associated pull request for more information.
2026-09-02 14:28:44 -07:00
Matthew Beck 124bf44809 release: cut the zone.js-0.16.3 release 2026-09-02 14:19:15 -07:00
Matthieu Riegler f44bf0fe22 ci: move packages/private under fw-general
This doesn't need dev-infra approval as its mostly testing utils.
2026-09-01 14:42:04 -07:00
Kam c03e872ed9 docs: highlight the search tutorial @for block as Angular
The block quotes a `.ts` file but declares `language="html"`, and shiki's
HTML grammar does not know Angular control flow, so the whole `@for` line
renders unstyled. Use `angular-ts`, matching the other blocks in the
tutorial.
2026-09-01 14:41:31 -07:00
aparziale 1d9e445d1a fix(vscode-extension): handle escaped delimiters in inline template and styles highlighting
The TextMate grammars for inline templates and inline styles ended the
string at the first occurrence of the delimiter, so an escaped delimiter
(e.g. \`) terminated the highlighting prematurely and the rest of the
template was no longer highlighted as HTML.

Escape sequences are now consumed before delegating to the HTML/CSS
grammars, so escaped delimiters no longer end the string. Also removes
the stray pipes from the string delimiter character class, which
unintentionally matched a literal '|'.

Fixes #65493
2026-09-01 14:40:44 -07:00
Kristiyan Kostadinov 05c4d5a835 feat(core): add utility for testing directives
Adds `TestBed.createDirective` to make testing directives easier.

Fixes #54164.
2026-09-01 14:40:05 -07:00
Matthieu Riegler 9f440907e8 refactor(core): remove old deferredImports structure
This finishes the migration to the keyed object structure
2026-09-01 09:41:10 -07:00
Doug Parker 6e299da8cf feat(forms): hard-code readOnlyHint and untrustedContentHint for WebMCP implicit signal forms
Signal forms can safely assume `{readOnlyHint: false, untrustedContentHint: false}` given their context. A form _must_ alter page DOM (or else how would a user interact with it) and is therefore definitionally side-effectful. We also assume returned content is trusted, given it is currently hard-coded or derived from application errors.

In the future, we might want to consider cases where application errors are explicitly untrusted or where application developers choose to customize the response text with something which might be untrusted. For now, that's out of scope and we'll worry about it when a compelling use case arises.
2026-09-01 09:39:20 -07:00
Doug Parker 91a2bf8425 feat(core): support annotations in WebMCP tool declarations
This updates `declareExperimentalWebMcpTool` to allow annotations to be provided to opt-in the tool explicitly into being read only or returning untrusted content.
2026-09-01 09:39:20 -07:00
Matthieu Riegler faafd18a4c fix(compiler-cli): check uninvoked signal aliases in extended diagnostic
Extended template diagnostic interpolated_signal_not_invoked previously
only checked symbols with kind === SymbolKind.Expression. When a signal
is aliased via @let (or a template variable), getSymbolOfNode returns
a LetDeclarationSymbol (or VariableSymbol), causing the diagnostic to
skip checking uninvoked usages of signal aliases in interpolations and
bindings.

This commit updates interpolated_signal_not_invoked to also check
LetDeclarationSymbol and VariableSymbol, using the usage site's AST
name span for reporting the diagnostic.

Closes #70476
2026-09-01 09:38:21 -07:00
Kam b70edd2768 fix(docs-infra): parse docs-callout attributes correctly
Three ways a callout could be misparsed:

- A title quoted with `'` or a backtick was dropped, leaving an empty
  heading. Two callouts lose their title on angular.dev today, on
  guide/forms/template-driven-forms and guide/i18n/prepare. The first has
  to use single quotes because its title contains `"pristine"`.
- A title containing `>` was dropped, because the attribute capture
  stopped at the first `>` even inside a quoted value.
- The severity was matched anywhere in the tag, so a title such as
  "Why this is important" silently rendered an important callout.

Scan attributes with quoting in mind, accept all three quote characters
as #69268 did for docs-code-block, and match the severity flags against
the tag with attribute values removed. The i18n callout also spelled the
attribute `header`, which the extension has never read.
2026-09-01 09:36:47 -07:00
hawkgs 00ec65546b refactor(devtools): fix signal details UI
Fix different action buttons and value preview container size.
2026-09-01 09:33:35 -07:00
Kam a92f6057d3 refactor(docs-infra): remove two more unreferenced guide images
`input.svg` and `output.svg` are leftovers that #70335 missed. Their
last reference was deleted by #54829 when the AIO guides were removed,
and nothing in the repo mentions them or their directory. Removing both
empties `adev/src/assets/images/guide/inputs-outputs`.
2026-09-01 09:32:27 -07:00
Shuaib Hasan Akib b5ce15c659 refactor(core): use native Promise.withResolvers() in tests
Replaces the temporary `promiseWithResolvers` polyfill with the
native `Promise.withResolvers()` API in test files and Updates the TypeScript configuration to include the `es2024.promise`.
2026-09-01 09:31:48 -07:00
arturovt 8975b4346d docs: add NG0991 error page and document rxResource's completion contract
RESOURCE_COMPLETED_BEFORE_PRODUCING_VALUE had no guide, no JSDoc on
RxResourceOptions.stream, and — since the code was positive rather
than negative — could never get an auto-linked docs page even if one
existed. Flip it to -991, add the NG0991 reference page, and document
the "stream must emit a value or an error before completing"
requirement on stream's JSDoc and in the RxJS interop guide.

Also documents and tests that an unguarded template read of an
errored resource's .value() propagates to the global ErrorHandler,
and recommends guarding with .hasValue() as defense in depth.

httpResource can throw the same error, but for a different reason:
its internal request Observable isn't something app code writes
directly, so an empty completion there is almost always an
HttpInterceptor swallowing the response (catchError(() => EMPTY))
rather than a stream authored in the resource() call itself. The page
covers both APIs with guidance matched to what's actually going on
for each.
2026-09-01 09:31:00 -07:00
arturovt ca38305976 docs: explain that errors during early app startup miss ErrorHandler
There's a short window where Angular can't send errors to ErrorHandler
yet: while it's still building the root module or root component. It
needs that root instance to look up the ErrorHandler you provided, so
an error thrown before it exists just becomes a normal uncaught error
instead.

This mostly bites people using Angular elements, where a custom element
tag already sitting in the page gets upgraded (and its component built)
the moment you call customElements.define, which can happen very early.

Added a short section to the error handling guide explaining why this
happens and the usual ways around it: setTimeout, APP_BOOTSTRAP_LISTENER,
or moving element registration to ngDoBootstrap.

Fixes #29211
2026-09-01 09:26:44 -07:00
oerol 9fd77852fb docs: fix global target event listener example 2026-09-01 09:26:07 -07:00
Santosh Yadav e1bf5393ad docs: Update request handler to use handle method
there is no request method the correct method is hanlde
2026-09-01 09:25:24 -07:00
Angular Robot 1b0d861fe5 build: lock file maintenance
See associated pull request for more information.
2026-09-01 09:22:54 -07:00
SkyZeroZx d8e74e7d39 docs(docs-infra): improve update checkbox accessibility
Associate each recommendation with its checkbox so assistive technology has a descriptive label and non-interactive text toggles the control. Keep embedded links independently operable.
2026-08-31 20:33:18 -07:00
lazerg f72600eadd fix(migrations): skip tsconfig files of non-Angular projects
Only touch tsconfig files for targets that use an Angular builder, including community ones like Nx, so non-Angular projects in mixed workspaces are left alone.

Fixes #69837
2026-08-31 20:31:31 -07:00
Angular Robot 87d38ec3ff build: lock file maintenance
See associated pull request for more information.
2026-08-31 15:37:10 -07:00
Stefan 4c4a705ce3 fix(zone.js): preserve accessor and non-enumerable event listener options
`copyEventListenerOptions` copied the caller's options with `{...options}`
before forwarding to the native `addEventListener`. Object spread only
copies own enumerable data properties, whereas the native call reads
each dictionary member via WebIDL — a plain `[[Get]]` per member, which
invokes accessors and ignores enumerability. The copy was therefore
lossy in a way the native call is not:

- `Object.defineProperty(opts, 'passive', { get })` (the shape used by
  MDN's passive-listener feature test) — the getter was never invoked,
  so libraries that use the feature test fall back to the legacy boolean
  and register every listener as non-passive.
- `Object.defineProperty(opts, 'capture', { get: () => true })` — the
  listener was silently registered on the bubbling phase.
- `Object.defineProperty(opts, 'once', { get: () => true })` — the
  listener fired on every dispatch.

`signal` was already special-cased for `AbortController.prototype.signal`
after #54142; that patch generalises the workaround to every recognised
member.

The copy itself was the correct fix for #54142 (frozen/readonly options)
and is preserved. The fix reads each recognised member from the source
via `[[Get]]` when the spread did not, which recovers accessors and
non-enumerable properties without double-invoking any getter. The list
of recognised members is hoisted to module scope so it isn't allocated
on every `patchEventTarget` invocation.

The call site is reordered to `buildEventListenerOptions(
copyEventListenerOptions(...))` so the passive-events code path also
spreads a normalised data object rather than the caller's raw input.

Fixes #70431

Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-08-31 15:21:37 -07:00
Roman 0904f90b13 fix(core): cancel stale debounce timers to prevent timer leaks
The debounce() utility scheduled a setTimeout when using a numeric wait value, but the scheduled timer was never cleared when a new value arrived, the observable threw, or the injector was destroyed. This caused pending timers to fire after invalidation and leak beyond the owner's lifecycle.

Refactor timer cancellation into a dedicated helper and track the pending timer id so any stale timer is cleared on new values or teardown. Adds tests covering cancellation on new values, errors, and injector destruction.
2026-08-31 15:07:31 -07:00
Jessica Janiuk f3ed75eb6b ci: remove shared primitives pullapprove group
This group is no longer necessary as responsibilities for that are now spread amongst teams more equally.
2026-08-31 15:03:05 -07:00
Alan Agius b3bb36ad87 fix(platform-server): resolve HTTP(S) URLs without authority as relative during SSR
Under the WHATWG URL standard, HTTP and HTTPS URLs lacking an authority
(e.g., `http:/path` or `http:path`) resolve as relative paths when resolved
against an origin of the same scheme. Previously, `relativeUrlsTransformerInterceptorFn`
treated any URL with a scheme as an absolute URL, bypassing base resolution in SSR
and allowing Node fetch to parse the path as a cross-origin host.

This commit updates SSR URL resolution and the HTTP interceptor to ensure
HTTP(S) URLs without an authority are resolved against the current origin,
preventing unexpected origin changes and aligning SSR with browser behavior.

Fixes #70447
2026-08-31 13:22:53 -07:00
Kristiyan Kostadinov 38861ac41b fix(forms): avoid writing to name input on ControlValueAccessor
Fixes that signal forms were overridding the `name` input of the CVA with an auto-generated one. This can break directives like `mat-radio` that assign their own `name`.

Fixes #69677.
2026-08-31 13:21:15 -07:00
Matthieu Riegler 9cf7b44f7c build: remove explicit strict options
Those options are enabled by default, they don't need to be explicit.
2026-08-31 13:17:00 -07:00
Kam acdac1cb89 fix(docs-infra): restore the edit link on decorative header pages
The 34 pages using `<docs-decorative-header>` render their title
through `getPageTitle()` without passing the markdown file path, so
the "Edit this page" link is silently dropped. Every other page keeps
it. Compare https://v19.angular.dev/guide/components, which still has
the pencil, against https://angular.dev/guide/components, which does
not.

`filePath` was required until #63536 made it optional, so API
descriptions with no editable source could render a title without a
link. That removed the compile error forcing the decorative header to
supply it, and the argument was lost with nothing to catch it.

Pass the path again and cover both header variants with tests, since
the edit link had no coverage at all.
2026-08-31 13:14:25 -07:00
Kam d9afca095b fix(docs-infra): reject unclosed paired docs elements
An unclosed `<docs-step>` or `<docs-card>` produces no error, just wrong
output, so the two cases fixed in the previous commit went unnoticed for
years.

Validate that the paired custom elements balance before parsing. A
mismatch now names the file and the counts instead of silently
swallowing a section.
2026-08-31 11:31:02 -07:00
Kam 0752282c8f docs: close the unclosed docs-step tags in two guides
`reactive-forms.md` and `app-shell.md` each open a `<docs-step>` that is
never closed. The tokenizers match up to the *next* closing tag instead
of failing, so the unclosed tag pulls in the content that follows and
leaves the block after it unparsed in the output.

On https://angular.dev/guide/forms/reactive-forms the "Creating nested
form groups" section shows raw source: "To create a nested group in
`profileForm`, add a nested `address` element", backticks and all. Its
heading is swallowed into the unclosed step instead of being an h3, and
the page renders 20 of its 21 steps. On
https://angular.dev/ecosystem/service-workers/app-shell the third step
is missing entirely.

`reactive-forms.md` has been broken since #52536, `app-shell.md` since
#55550.
2026-08-31 11:31:02 -07:00
Kam 46b02cc181 docs: correct stale visibleLines ranges in the first-app tutorial
The tutorial's example files shifted without the README line references
following, so several steps point at the wrong code. In two cases every
requested line is past the end of the file; on the inputs step this renders
as a code block with no lines visible at all.
2026-08-31 11:26:37 -07:00
Kam cd3c8cdd3a docs: correct out-of-range highlight indices in two code blocks
Both indices point past the end of their block, so the intended lines are
never highlighted. The reactive forms block renders with no highlight at all,
and the first example in output-interop.md highlights nothing while its
sibling block is unaffected.
2026-08-31 11:25:03 -07:00
Kam 731c838dbb docs(zone.js): point the Bluebird link at the project repo
bluebirdjs.com no longer resolves. npm lists the GitHub repo as the package's
homepage, so the link now goes there.
2026-08-31 11:21:42 -07:00
Kam 519c52eea0 docs: update dead links in the contributing docs
The fork guide link 404s since GitHub retired help.github.com, and the
rules_nodejs debugging docs moved to the bazel-contrib org. Also points the
git setup link straight at its current home rather than through a redirect.
2026-08-31 11:17:37 -07:00
Angular Robot 563850e860 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-08-28 18:05:00 -07:00
Angular Robot 444b4652a9 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-28 18:01:05 -07:00
Kam 2a4903fec1 docs(core): repoint or drop dead jsperf links in the render3 notes
jsperf.com now returns 410 for every benchmark. Two of them still exist on the
successor site and are repointed at jsperf.app; the other five are gone, so the
links are removed and the performance claims they backed are kept.
2026-08-28 18:00:36 -07:00
Angular Robot 2877c3b995 build: update dependency node to v24.20.0
See associated pull request for more information.
2026-08-28 17:59:46 -07:00
Shuaib Hasan Akib 54f67e1318 docs: correct highlight index for pipe examples in README 2026-08-28 17:58:55 -07:00
Kam 1e8dd80458 build: point the integration .gitignore comments at live GitHub docs
help.github.com/ignore-files/ 404s since GitHub retired that domain. Five of the
files still linked to it over plain http as well.
2026-08-28 17:57:15 -07:00
Michael Small 0017b87b52 docs: update link/file for JetBrains AGENTS.md 2026-08-28 17:56:37 -07:00
leonsenft 34817da735 refactor(core): defer foreign component rendering to post-update pass
Foreign components imported via foreignImports and created by the
ɵɵforeignComponent instruction were previously rendered eagerly in the
creation phase (rf & 1) of the template. This restricted which
properties could be passed to foreign component props, as parent-bound
inputs (@Input(), input(), input.required()), properties initialized in
ngOnInit(), and pull-based view queries (viewChild()) were not yet
initialized at creation time.

This change defers foreign component rendering to run as a view effect
during the update pass:
- Update ɵɵforeignComponent in core to schedule component rendering via
  createViewEffect (executed in runEffectsInView during refreshView),
  executed with setActiveConsumer(null) to prevent reactive context
  leakage and destroyed immediately upon first execution.
- Update ɵɵforeignComponent to strictly accept props as a factory function
  (() => props) or null.
- Update the compiler template pipeline to wrap foreign component props
  in an arrow function closure (() => ({ ... })).
- Hoist creation-time foreign content projection instructions
  (ɵɵforeignContent, ɵɵforeignContentFn) into creation-phase variable
  declarations before ɵɵforeignComponent so creation-time context is
  captured safely.
2026-08-27 21:05:33 -07:00
Matthieu Riegler 4c55a36a87 refactor(compiler): deduplicate explicitly deferred types to prevent syntax errors
When `@Component.deferredImports` maps blocks to arrays of dependencies, an explicitly
deferred dependency might be defined in multiple blocks (e.g. `block1: [CmpA], block2: [CmpA]`).
Previously, these were appended to the `explicitlyDeferredTypes` array without deduplication.
When generating the `setClassMetadataAsync` wrapper for development mode, the compiler
used this array to generate callback parameters for dynamic imports. This resulted in
duplicate parameter names in the callback signature `(CmpA, CmpA) => { ... }`, which
causes an `Uncaught SyntaxError` when V8 parses the module in strict mode.
This commit deduplicates `explicitlyDeferredTypes` in the `ngtsc` component handler, and
adds a secondary deduplication check in the `r3_class_metadata_compiler` generator to
ensure duplicate parameter names are never emitted.
2026-08-27 21:04:07 -07:00
Kam ad22e89d4d refactor(devtools): point the .gitignore comment at live GitHub docs
help.github.com/ignore-files/ 404s since GitHub retired that domain.
2026-08-27 13:44:43 -07:00
Andrew Scott 6f1dc268cc docs(router): Add router resource docs
Adds doc (but no navigation entry) for router resources. Feature not released yet
but getting documentation in place.
2026-08-27 12:45:27 -07:00
Andrew Scott 4fc45a9b38 refactor(compiler-cli): index bound directive inputs and outputs in templates
Update the template indexer to discover and record bound directive inputs (property bindings, static text attributes) and outputs (event bindings).

This associates template binding identifiers with their target directive or component class declarations, enabling indexers and language tooling to properly resolve and cross-reference bound directive inputs and outputs.
2026-08-27 10:23:32 -07:00
Angular Robot 6f91982c0d build: update dependency vscode-languageserver-textdocument to v1.0.14
See associated pull request for more information.
2026-08-27 10:22:46 -07:00
Kam 843a65cba0 fix(docs-infra): point the tutorial .gitignore at live GitHub docs
The common tutorial scaffold's .gitignore opens with a link to
help.github.com/ignore-files/, which 404s. That directory is copied into every
tutorial and playground, so the dead link ships to anyone who opens one.
2026-08-27 10:20:49 -07:00
Angular Robot c2d4070c36 build: update all non-major dependencies
See associated pull request for more information.
2026-08-27 07:59:47 -07:00
Angular Robot bcc0e9206f build: update cypress-io/github-action action to v7.4.3
See associated pull request for more information.
2026-08-27 07:55:41 -07:00
Angular Robot 93ca7ab071 build: update bazel dependencies
See associated pull request for more information.
2026-08-27 07:51:21 -07:00
leonsenft 133cafda42 release: cut the v22.2.0-next.4 release 2026-08-26 17:16:48 -07:00
leonsenft a2b4379bb0 docs: release notes for the v22.1.4 release 2026-08-26 17:11:47 -07:00
leonsenft 9b70174100 docs: release notes for the v21.2.22 release 2026-08-26 17:00:16 -07:00
leonsenft 575bb6e08a docs: release notes for the v20.3.30 release 2026-08-26 16:38:40 -07:00
Angular Robot 2e6a05750e docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-08-26 15:50:33 -07:00
hawkgs c1ac4b750a refactor(devtools): convert remaining console calls to the custom log
Convert the remaining calls introduced by the #70254.
2026-08-26 15:38:33 -07:00
Angular Robot 8c26fc74e5 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-26 15:37:41 -07:00
Andrew Scott 66d505e287 refactor(core): Decouple ɵɵFactoryDeclaration and ɵɵInjectableDeclaration from type parameter T.
When compiling under standalone compilation, generated runtime static declarations (static ɵfac and static ɵprov) are emitted into preprocessed TypeScript files and visible to the compiler during semantic typechecking.

When a subclass extends a base class where the subclass is not structurally subtype-compatible with the superclass (such as differing generic type constraints, contravariant method parameters, or EventEmitter<this>), TypeScript's class static side heritage check (TS2417) fails because ɵɵFactoryDeclaration<T> and ɵɵInjectableDeclaration<T> structurally referenced the instance type T.

This change updates ɵɵFactoryDeclaration to return any instead of T, and sets factory return and value types in ɵɵInjectableDeclaration to any. This decouples static side inheritance from T, resolving TS2417 errors across subclassed components and injectables while preserving .d.ts metadata indexing and assignability to ɵɵdefineInjectable. This brings ɵfac and ɵprov into alignment with other Ivy declarations (ɵcmp, ɵdir, ɵpipe, ɵinj), which already treat their generic parameters as phantom metadata.
2026-08-26 13:45:05 -07:00
Alan Agius 1d0945fa32 release: bump Angular DevTools version to 1.21.0 2026-08-26 09:56:48 +02:00
leonsenft 915a03ae85 fix(core): explicitly reject foreign components in JIT mode
Foreign components are only supported in AOT mode. Using them in
JIT mode previously resulted in silent failures or confusing runtime
errors (such as unknown element errors or crashed template ingestion).

This commit adds explicit validation in JIT compilation:
- Throws an error during component compilation if `foreignImports` is
  specified on `@Component`.
- Throws an error during standalone import verification if a foreign
  component is mistakenly passed to `@Component.imports`.
2026-08-25 16:28:32 -07:00
leonsenft a46292af26 fix(compiler-cli): default template diagnostic related message source file to template
For external templates (using `templateUrl`), primary diagnostics are
reported against the synthetic `ts.SourceFile` representing the HTML
template document. However, secondary related messages (such as those in
`foreign_component.ts` and `oob.ts`) were explicitly passing the
component's TypeScript file as `sourceFile`.

Because the character offsets (`start` and `end`) originate from the
HTML template AST, associating them with the TypeScript source file
caused IDEs and CLI diagnostics to map HTML offsets onto the `.ts` file,
resulting in corrupt or out-of-bounds source locations.

This commit resolves the issue by:
1. Making `sourceFile` optional in `makeTemplateDiagnostic` and related
   checker interfaces (`TemplateTypeChecker`, `TemplateContext`).
2. Defaulting `relatedMessage.sourceFile` to the template's source file
   (`sf` for external/indirect templates, or the component `.ts` file
   for direct inline templates) when not explicitly provided.
3. Removing explicit `sourceFile: this.sourceMapping.node.getSourceFile()`
   mappings from `foreign_component.ts` and DOM element checks in
   `oob.ts`, allowing them to automatically resolve to the template file.
4. Adding unit test coverage for external templates encountering foreign
   component conflicts with related messages.
2026-08-25 16:19:32 -07:00
arturovt 83f7695b2e fix(core): throw coded RuntimeErrors instead of crashing when hydration/rendering can't find an expected DOM node
This started from a real production crash trace:

    TypeError: Cannot read properties of null (reading 'nextSibling')

Traced through a minified bundle back to siblingAfter() in
packages/core/src/hydration/node_lookup_utils.ts. It walks forward a
fixed number of DOM siblings during hydration, based on how many the
server rendered. Its only guard, validateSiblingNodeExists(), is
gated behind ngDevMode and stripped from production builds. If the
client DOM has fewer real siblings than the server-serialized data
expects — client/server render diverged, or something outside
Angular (a browser extension, an injected script) removed a node —
the loop ran fully unguarded in production: currentNode went null
partway through, and the next iteration's currentNode.nextSibling
threw a raw, uncoded TypeError instead of a coded, debuggable one.

Reproduced first, not just theorized: added a test that server-
renders a @for loop with 3 items, removes 2 of them before hydration
runs, and confirmed it actually throws that exact TypeError against
the original code before touching anything.

Fix: add a null check at the top of the loop, matching the pattern
already used for the existing NG0500/NG0502 hydration checks in
element.ts — the dev-mode check runs first as before (a no-op in
production), and the new check is a pure safety net that only fires
once that dev-mode check has already been compiled away. In dev mode
this is provably dead code, so nothing about dev behavior changes.
Coded as NG0501 (HYDRATION_MISSING_SIBLINGS, already existed).

While investigating, found and fixed two more call sites with the
exact same shape of bug — a dev-only check that leaves production
completely unguarded:

- navigateToNode() (same file): walks an explicit "firstChild /
  nextSibling" navigation path recorded for nodes that can't rely on
  simple sibling-walking (e.g. content right after an <ng-content>
  slot). Its only guard was also ngDevMode-only. Added the same
  production safety net, both mid-loop (the raw-crash case) and
  post-loop (where it could previously return null silently despite
  the function's return type promising a non-null RNode). New code:
  NG0509 (HYDRATION_MISSING_NODE_ON_PATH).

- getParentRElement() (render3/node_manipulation.ts): typed its
  tNode parameter as always non-null, but a real production trace
  showed it can be null at runtime, crashing on tNode.parent with no
  useful information. Widened the type to TNode | null and added a
  guard that throws a coded error instead. New code: NG0510
  (PARENT_NODE_NOT_FOUND).

  Unlike the other two, this one isn't gated behind ngDevMode at all
  in the original code — it reproduces unconditionally. Decoded the
  actual production minified stack trace against this source
  (matched every frame character-for-character) to find the real
  cause instead of guessing: an @if/@switch branch's content is its
  own embedded template with its own TView, built lazily the first
  time that branch renders. If an error interrupts that first pass —
  here, a hydration mismatch on the branch's second child, after the
  first child's TNode was already created — TView.firstCreatePass
  still gets flipped to false in render.ts's `catch` block before the
  error propagates, permanently marking that TView as corrupted.
  Unlike a component's TView (rebuilt from scratch next time via
  getOrCreateComponentTView()'s incompleteFirstPass check), nothing
  rebuilds an embedded view's TView. The next time that exact branch
  is selected again, its instructions read straight from the
  corrupted tView.data instead of creating a fresh TNode, and any
  node past the interruption point is still null.

  The real test added for this (full_app_hydration_spec.ts) exercises
  that whole chain for real: a hydration mismatch on an @if branch's
  second child, then re-entering the same branch. Confirmed it throws
  the exact byte-for-byte production error message ("Cannot read
  properties of null (reading 'parent')") without the fix, and the
  coded NG0510 with it. This replaces an earlier synthetic unit test
  that just cast a variable to null to bypass the type system rather
  than reproducing the actual failure.

  Note: a more thorough fix would rebuild the corrupted embedded TView
  itself (mirroring getOrCreateComponentTView()), which does make the
  crash disappear — but doing that surfaces a second, separate bug:
  the aborted first attempt's partially-created LView/DOM is never
  torn down, so the retried branch's content gets appended alongside
  leftover orphaned nodes instead of replacing them, corrupting
  content silently instead of crashing loudly. That's a materially
  bigger fix (proper LView cleanup after a mid-creation exception) and
  is intentionally out of scope here; this commit keeps the narrower,
  safe fix (a clear coded error) rather than trading a loud crash for
  silent data corruption.

Along the way, deduplicated describeDomNode(), which existed as two
near-identical private copies (one in this file's own NG0500 check,
one in platform-browser's dom_renderer.ts insertBefore check) and
moved it into core's hydration/error_handling.ts, shared via the
private ɵdescribeDomNode export.

That function was then removed from every production code path
entirely, per review feedback: computing a human-readable node
description is debug-oriented work that shouldn't ship unconditionally
in production bundles, regardless of how cheap it is — production
should get the bare coded error only, the same as everywhere else in
this file. All three fixes above follow that: ngDevMode && 'message'
in production, no computed description. Confirmed the removal
actually shrinks output, not just assumed it: regenerated all 8
affected bundling symbol goldens, and each one shows exactly one
symbol removed — "describeDomNode" — and nothing else.
2026-08-25 16:16:22 -07:00
Matthieu Riegler 9c52dbf216 refactor(compiler-cli): ensure eager dependencies used inside defer blocks are not dropped
When `onlyExplicitDeferDependencyImports` is enabled, dependencies that are used exclusively inside a `@defer` block but are provided eagerly (i.e., in the `imports` array but omitted from `deferredImports`) were incorrectly dropped from the generated `dependencies` array.

This occurred because the template binder intentionally omits directives used only inside defer blocks from the eager directives list, and the defer block resolver only tracks dependencies explicitly listed in `deferredImports`.

This commit fixes the issue by ensuring that any template dependency used within a defer block that is not deferred is explicitly preserved as an eager dependency, ensuring it is available at runtime.
2026-08-25 16:08:58 -07:00
Kam ddfd8a8e9b refactor(docs-infra): remove example configs for tooling that no longer exists
An example-config.json marked a directory as a doc example and told aio's
example tooling which boilerplate to use and what to run against it. #56496
removed that tooling in June 2024. Eight of these fifteen files are empty and no
code has read any of them since; the name survives only in the zip and
StackBlitz exclude lists, which skip it rather than open it.
2026-08-25 15:21:49 -07:00
Andrew Scott df83a34088 refactor(router): add component input binding support for router resources
Integrates component input binding (via `withComponentInputBinding()`) with router resources.
2026-08-25 15:20:56 -07:00
Lazizbek Ergashev 3848b7f8bc docs: clarify onSameUrlNavigation reload behavior
fixes #70367
2026-08-25 11:27:10 -07:00
hawkgs 07605ba793 feat(devtools): implement CD analyzer (#70254)
Implement component highlighting on change detection cycles along with embedding
the component-specific data to the directive/component tree explorer.

Closes #59057

PR Close #70254
2026-08-25 10:35:42 -07:00
hawkgs 82882fae51 refactor(devtools): add TTL and outline style to the highlighting mechanism (#70254)
Add the ability to automatically destroy created highlights by a provided TTL;
Add the option for outline style of the highlight overlays;
Add `prefer-inset` label position;

PR Close #70254
2026-08-25 10:35:42 -07:00
Kam 90fc9475f2 refactor(docs-infra): remove example code that nothing references
The `built-in-directives` and `structural-directives` example apps are no
longer referenced. Two guide rewrites moved their pages to inline code fences
and dropped the last references without removing the apps: #69134 for
structural directives, and #69822 for built-in directives, whose page is gone
entirely. Both apps sat inside the `embeddable` glob, so they were still
compiled as preview components on every build.

The example e2e suites are excluded from every consumer by design: previews
ignore `*.e2e-spec.ts` and `*.po.ts`, and the zip and StackBlitz pipelines
both list the suffix in `EXCLUDE_FILES`. They could not run in any case,
since every spec declares a `driver` and never assigns it before calling
`driver.get('')`, left over from an abandoned protractor to selenium
migration.

The eslint configuration in the same directory is also unused. Nothing in the
repository depends on eslint, and `tsconfig.eslint.json` extends a path that
no longer exists.
2026-08-25 10:11:19 -07:00
Kam 7da60d1920 fix(docs-infra): redirect three removed pages instead of 404ing
`guide/http/security` and `reference/concepts` both still exist as content but
neither is routed, so each falls through to the 404 shell.

`guide/http/security` was navigable from November 2023 until #54365 removed its
entry in February 2024. #55029 then copied its XSRF sections into the security
guide, which already covered XSSI, and #55060 repointed the remaining links, so
it now redirects to `/best-practices/security`.

`reference/concepts` was added by #54365 and removed by #58694 in November
2024, leaving it navigable for nine months without a redirect. The same commit
also removed `guide/ngmodules`, the route its only card linked to, so both now
redirect to `/guide/ngmodules/overview`, alongside the four `guide/ngmodules/*`
paths already redirected there.

Both pages are removed, along with the Bazel package that existed only to build
the concepts page, and the stale `llms-list.md` entry for the HttpClient page.
The security guide takes its place in that list, so `llms-full.txt` keeps its
XSSI coverage and picks up CSP, Trusted Types and sanitization with it.
2026-08-25 10:08:42 -07:00
Kam a67d4027e2 refactor(docs-infra): remove the Windows tile icons and other unused icons
The `msapplication` tile configuration serves no purpose now, so the
`browserconfig.xml` it points at, the five tile images and the two meta tags
in `index.html` are removed together.

`shared-docs/icons/twitter.svg` is also unused, left behind when the footer
moved to X and Bluesky. Its three siblings in that directory are all still
referenced.
2026-08-25 10:02:43 -07:00
Alan Agius 3e924cc8db fix(platform-server): avoid stripping unicode whitespace during url resolution
Avoid trimming urlStr with String.prototype.trim() in resolveUrl to ensure URL parsing and resolution align with the WHATWG URL standard.
2026-08-25 09:59:04 -07:00
Xia Chao 7596548e9b fix(common): use locale NaN symbol in number formatting
Non-finite values all used NumberSymbol.Infinity, so formatNumber(NaN)
rendered as infinity. Locale data already defines NumberSymbol.NaN.
2026-08-25 09:58:14 -07:00
Matthieu Riegler 3be5facf04 ci: pass required inputs for adev preview artifact upload
The `pack-and-upload-artifact` action from `dev-infra` recently added conditional steps that require `triggering-label` and `angular-robot-key` to be passed. Without these inputs, the internal action steps were silently skipped, resulting in no artifact being uploaded. This caused the subsequent deploy workflow to fail when it couldn't find the `adev-preview` artifact.
2026-08-25 09:57:22 -07:00
Georgi Serev 1371c946aa refactor(devtools): use a custom logger and error
Use a custom logger that prefixes the messages with `[Angular DevTools]`;
Add ability for dev-only log messages;
Add Angular-DevTools-specific `Error`;
2026-08-25 09:55:04 -07:00
root 74b294cd51 fix(compiler-cli): retain metadata for strict standalone errors
This fix ensures that metadata is properly retained when processing
strict standalone component errors for improved error diagnostics.
2026-08-25 09:54:06 -07:00
Angular Robot 1426f5ecf5 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-24 15:53:22 -07:00
Cameron Smick 82a767535e feat(devtools): add "Watch signal" button to signal-details component
Add a "Watch signal" button to the signal-details component to allow users to "watch" changes to the associated signal.
2026-08-24 15:35:44 -07:00
Cameron Smick d45bd2f53d refactor(core): implement toggleWatchSignal for DevTools signal debugging
Implement \`toggleWatchSignal(id)\` in \`signal_debug.ts\` to enable toggling reactive watch listeners on individual signal graph nodes.
- Create reactive \`Watch\` instances using \`createWatch\` to log signal value/state changes to the console when active.
- Use \`WeakRef\` mapping and \`FinalizationRegistry\` (\`watchCleanupRegistry\`) so active watches do not retain strong references to signal nodes or prevent garbage collection.
- Expose \`watched\` status on \`DebugSignalGraphNode\` and publish \`toggleWatchSignal\` onto \`window.ng\` in development mode.
- Add acceptance tests covering watch activation, signal mutation logging, manual disposal, GC cleanup, and safe invalid ID handling.
2026-08-24 15:35:44 -07:00
SkyZeroZx 168a324cce fix(core): prevent TransferState prototype pollution
Store transfer state and serialization callbacks in null-prototype dictionaries, and only read values that belong to the store. This keeps special state keys from changing lookup behavior or exposing inherited cache entries.

Fixes #70265
2026-08-24 15:34:07 -07:00
splincode f275d289a0 refactor(router): replace internal any types
Infer URL parameter values as strings and type preloading work as Observable<void> to match the values produced by these internal flows.
2026-08-24 15:27:51 -07:00
Andrew Scott 0d7ae16350 refactor(core): loosen return type of ɵɵFactoryDeclaration to any
When a derived class inherits from a base class, TypeScript enforces that static
properties on the derived class are assignable to those on the base class.
Because `ɵɵFactoryDeclaration<T, ...>` had a return type of `T`, static `ɵfac`
members across inheritance hierarchies could result in type incompatibilities
(for example, when dealing with generics or differing class shapes where the
derived factory return type is not compatible with the base class factory).

Updating the return type of `ɵɵFactoryDeclaration` from `T` to `any` avoids
these static type conflicts across inheriting classes.
2026-08-24 15:26:05 -07:00
Matthieu Riegler e9ba39d671 fix(compiler-cli): Produce correct tcb expression for optional chaining
The semantics of optional chaining changes when there are extra parenthesis. We need to make sure that we do not introduce some unnecessary ones.

fixes #70143
2026-08-24 15:21:17 -07:00
Angular Robot 671d8d395e build: update all non-major dependencies
See associated pull request for more information.
2026-08-24 10:49:59 -07:00
aminesbdev d953d2eda9 docs: add missing tap import and AppConfig interface to environment configuration reference 2026-08-24 10:37:13 -07:00
Kam 5e8a70a010 fix(docs-infra): fail the build on duplicate heading anchors
Two headings on the same page can generate the same anchor id, and every
link to it then resolves to whichever comes first. Nothing caught this
because the route manifest keeps anchors in a `Set`, so a repeat collapses
into one entry before any check runs, and the existing link validation only
asks whether an anchor exists, which a duplicate satisfies.

The generator now inspects each page's headings while they are still an
ordered list and fails with the offending pages and anchors. The scanning
and the duplicate check move to `heading.mts` so they are covered by tests
next to `getIdFromHeading`, which should keep this from coming back.
2026-08-24 10:36:16 -07:00
Kam 698a14d735 fix(docs-infra): give duplicated headings their own anchor ids
Eight guides have headings that generate the same anchor id twice or more.
Because an id resolves to the first element that claims it, the table of
contents lists two entries pointing at the same place, the second section
cannot be reached from the ToC at all, and the copy link button on the
later heading hands out a URL for the earlier one.

On `guide/forms/reactive-forms` the two "Display the component" steps sit
5176px apart and both ToC entries scroll to the first.

Give the later heading on each page an explicit id with the `{#custom-id}`
syntax the pipeline already supports. Only later duplicates are changed, so
every anchor that resolves today keeps pointing at the same heading.
2026-08-24 10:36:16 -07:00
Kam 355a9d83e3 refactor(docs-infra): remove images no longer referenced by any doc
Most of these came over from the angular.io docs and were orphaned as adev
rewrote or dropped the guides that used them. Two are newer: a devtools
screenshot that was added but never referenced, and the logo left behind
when the Firebase Studio launcher was removed. All of them are still
copied into the build and served from angular.dev.

No markdown, template, stylesheet, TypeScript file or build target
references any of them, by filename or through a path built at runtime,
and the images are globbed into the build rather than listed, so nothing
else needs updating. Removes 78 files, 5.15 MB in total, and empties
nineteen directories.
2026-08-24 10:35:41 -07:00
Aleksander Bodurri 434acc506e refactor(devtools): update profiler instruction text for clearing recordings
I suspect this text used to be correct but became outdated after UI changes. These is no "refresh" button.
2026-08-24 10:34:37 -07:00
Kam 3074fdb3ab docs: repair the AST link in the AOT compiler guide
The link to the Wikipedia article on abstract syntax trees spelled the
underscores as asterisks, which 404s. The same link two paragraphs
earlier in this guide is correct.
2026-08-24 10:31:51 -07:00
Kam 39da06138b fix(docs-infra): repair redirects pointing at removed pages
Five redirects sent people to the home page instead of a guide, because
their target no longer exists: the four `guide/ngmodules/*` entries point
at `/guide/ngmodules`, which has no route, and
`guide/animations/transitions-and-triggers` had a plural in a target that
is registered as `transition-and-triggers`.

Two more resolved only after a second hop, redirecting to a path that is
itself a redirect.

The spec only checked that a `redirectTo` starts with a slash, which all
seven satisfied, so it now also checks that the target is a real page and
that it is not another redirect.
2026-08-24 10:31:14 -07:00
Kristiyan Kostadinov c18261f3fd build: enable stableTypeOrdering tsconfig flag
`stableTypeOrdering` was recently enabled in the internal builds. While there aren't any breakages in Angular, these changes enable it so we can catch potential issues earlier.
2026-08-24 10:27:15 -07:00
Lazizbek Ergashev 58b0cb4735 fix(compiler): scope animations declared in minified nested rules
The regular expressions in `_scopeAnimationRule` expect an `animation` or `animation-name` property to be preceded by whitespace or a semicolon, and its value to end at a semicolon. Minified CSS breaks both assumptions. Inside an at-rule the property follows a `{`, and the last declaration of a block has no trailing semicolon, so the closing `}` lands inside the captured value. The keyframe name is then left unscoped while the `@keyframes` rule itself is renamed, so the animation does nothing in a production build.

Accept `{` as a leading boundary and stop the value at `}`. The prefix is written back unchanged, and a declaration value cannot contain an unescaped `}`.

Fixes #70316
2026-08-24 10:25:03 -07:00
Alex Rickabaugh 1e35de536d fix(forms): use dot-access for readonly rule configuration
The readonly rule previously used 'when' in configOrLogic to determine if a configuration object was provided. Under property renaming/minification, the string literal property lookup fails and causes the rule to fall back to being permanently readonly.

This change switches to the dot-access form (configOrLogic?.when), matching hidden() and ensuring property renaming works correctly.
2026-08-24 10:24:31 -07:00
Kristiyan Kostadinov 42f6641120 build: remove scorecard workflow
The scorecard workflow has been replaced at the org level so these changes remove it from our workflows.
2026-08-24 10:24:05 -07:00
aminesbdev 15cf923f88 docs: modernize creating-services reference with signal state and asReadonly 2026-08-24 10:22:10 -07:00
aparziale bdc09e8183 fix(migrations): preserve registerLocaleData calls in standalone bootstrap migration
Currently the standalone migration only copies symbols referenced from the NgModule metadata into the main file. Top-level `registerLocaleData` calls, and the default imports they depend on, are dropped silently when the module file is pruned, which breaks locale resolution at runtime with a "Missing locale data" error.

Copies top-level `registerLocaleData` calls from the file of the bootstrapped module into the main file, and adds support for carrying over default imports which were previously skipped silently by the reference resolution.

Fixes #50886
2026-08-24 10:18:58 -07:00
aparziale 0f0d52e9c1 fix(language-service): honor quote style preference when generating imports
The quick fix and completion auto-import always generated the module specifier with double quotes, ignoring the user's quote preference and the style used in the file.

The generated import now respects the `quotePreference` from the TypeScript user preferences. When the preference is `auto` (or absent), the style is inferred from the first existing import in the file, mirroring TypeScript's own behavior. Files with no imports
keep the previous double-quote default.

Fixes #67108
2026-08-24 10:18:02 -07:00
Kam c6a6ad0a44 refactor(docs-infra): drop exclude patterns for examples that no longer exist
The `embeddable` glob excludes nine example directories. Four of them,
`testing`, `ssr`, `resolution-modifiers` and `dependency-injection`, were
removed by #66753 and #61686 without updating this file, so those patterns
match nothing.

Three of the four sit under a TODO about examples that do not compile. Those
were deleted rather than fixed, which leaves `reactive-forms` and
`form-validation` as the only two the note still applies to.
2026-08-24 10:16:18 -07:00
aminesbdev 719e1ada74 docs: add self-closing tags guideline to components reference 2026-08-24 10:05:35 -07:00
Matthieu Riegler 555369960a ci: add Alan as a zone.js reviewer
This updates the zone.js owners and adds alan-agius4 to compiler approvers.
2026-08-24 10:02:14 -07:00
splincode a4a428ece2 refactor(forms): type async validator subscription
Use the Subscription type returned by Observable.subscribe instead of storing async validator subscriptions as any.
2026-08-24 10:00:19 -07:00
Matthieu Riegler 030779c4f0 build: update dependency magic-string to v1
Magic-string is now ESM only.
2026-08-24 09:59:00 -07:00
Kam 51cb07e980 docs: point the LLM indexes at current pages, not redirects
`llms-list.md` feeds the generated `llms-full.txt`. Three of its DI
entries were left behind by a page rename: two named files that no longer
exist and one named a copy that had been superseded. The generator warns
on an unreadable file and carries on, so the build stayed green while
`llms-full.txt` quietly lost three DI guides and shipped a stale fourth.

`llms.txt` linked the same old URLs, which only reach their pages through
a redirect, plus `guide/hybrid-rendering`, which redirects to `/guide/ssr`
and duplicates the line above it.

Also removes `creating-injectable-service.md`, left behind by that rename
and reachable from nothing.
2026-08-21 12:36:50 -07:00
Kam eb6570b06d refactor(docs-infra): remove the orphaned home animation component
The new home page in #63662 stopped rendering `HomeAnimationComponent`
and its directory was left behind. The animation that runs today lives
in `features/home/animation`, which replaced it.

Nothing references the class, its `adev-home-animation` selector, or any
file in the directory, and no stylesheet or build target pulls it in.
2026-08-21 12:35:12 -07:00
Kam 4997521685 refactor(docs-infra): type the API manifest in the nav entries
`getApiNavigationItems` cast the manifest to `any` behind a TODO waiting
on #66252, which was closed without merging, so the three `any`s it
guarded were never going away on their own.

The real `ApiManifestPackage` cannot be imported here: navigation
entries are built as a standalone `ts_project` so the route generator
can consume them at build time, and it has no dependency on the app
tree. Declaring the handful of fields this file reads gets rid of the
`any`s without touching the build graph.
2026-08-21 12:29:38 -07:00
Lazizbek Ergashev 3438614f5e docs: warn against using in-memory-web-api in production 2026-08-21 12:27:39 -07:00
Kam 238d8bf98a refactor(docs-infra): hold editor diagnostics in a signal
`DiagnosticsState` carried a TODO to move off `BehaviorSubject` once
zoneless was turned on. adev has been zoneless for a while now, with no
zone.js dependency and an empty `polyfills` array, so the condition is
met and the TODO can go.

Both consumers now derive from the signal instead of subscribing. The
Console tab badge becomes a `computed`, and so does the code editor's
error list: the diagnostics are produced by a `linter()` configured with
a 400ms delay rather than arriving as a stream, so the rxjs chain was
only adding a further second before they were displayed. The errors box
stays dismissable through a `linkedSignal`, which reverts as soon as the
diagnostics change.
2026-08-21 11:50:42 -07:00
Kam 593f2d7e2e refactor(docs-infra): share the angular.dev origin constant
The angular.dev origin was declared twice as a local `ANGULAR_DEV`
const and hardcoded inline in two more places. It now lives once in
`core/constants/links.ts`, next to `ANGULAR_LINKS`.
2026-08-21 11:50:02 -07:00
Kristiyan Kostadinov f3c093df24 refactor(compiler-cli): add compiler option for enabling source locations
Adds an internal config options that allows us to enable source locations.
2026-08-21 11:45:30 -07:00
root 2ab5ff56de fix(core): preserve namespace for dynamic component hosts
Forward the insertion namespace when creating dynamic component hosts inside SVG or MathML.
2026-08-21 11:41:59 -07:00
Andrew Scott fa2aca969f refactor(router): add support for blocking router resources
Extends router resource integration to support blocking resources during navigation transitions.
2026-08-21 11:38:19 -07:00
Andrew Scott ad3c16562b docs: add guidelines for Object.create(null) PRs to PR review skill 2026-08-21 11:36:46 -07:00
Kristiyan Kostadinov 7ba082e08e fix(core): avoid prototype member collisions
Switches to using an object with a `null` prototype to avoid collisions.
2026-08-21 11:32:44 -07:00
Kristiyan Kostadinov 862a0c8ab3 fix(common): avoid prototype member collisions
Switches to using an object with a `null` prototype to avoid collisions.
2026-08-21 11:32:44 -07:00
Andrew Scott 779f67777d refactor(core): widen ɵɵclassProp value parameter type to any
When Angular type-checks host bindings and template class bindings
(`[class.foo]="expr"`), the Type Check Block (TCB) emits the binding
as a standalone expression statement (e.g. `(expr);`). This verifies that
the expression itself is syntactically and semantically valid (e.g. properties
exist on the component instance), but does not constrain the
expression to `boolean` because Angular evaluates class bindings using standard
JavaScript truthiness.

In classic `ngtsc`, the runtime Ivy instructions (`ɵɵdefineComponent`) were
generated only during the JS emit phase, after TypeScript type-checking had
completed. Thus, `tsc` never validated the arguments passed to `ɵɵclassProp`.

Under standalone commpilation, Ivy definitions are generated
directly into the TypeScript AST and type-checked by `tsc`. This causes `tsc`
to check the emitted `ɵɵclassProp('foo', expr)` call against the instruction's
declared signature. Because `ɵɵclassProp` was strictly typed as
`boolean | undefined | null`, any valid truthy non-boolean expression
(e.g., `1`, `items.length`, or non-empty strings) produces a `TS2345` compiler error.

At runtime, `ɵɵclassProp` delegates to `checkStylingProperty`, which evaluates
the value via truthiness (`!!value`). Widening the parameter type to `any`
aligns the instruction's type signature with Angular's binding semantics and
prevents type-checking failures during in-place compilation.
2026-08-21 11:26:00 -07:00
Konstantin S. 045746c18c docs(core): clarify toObservable synchronization behavior 2026-08-21 11:22:53 -07:00
Alex Rickabaugh 2e2c426e76 fix(compiler-cli): deduplicate deferred imports across multiple blocks
When @Component.deferredImports is defined as an object mapping block
names to dependency arrays, deduplicate entries when aggregating block
imports into the component-level flattened scope. This prevents
duplicate directive/component collisions in DirectiveMatcher when
multiple @defer blocks share dependencies.
2026-08-21 11:14:47 -07:00
Alex Rickabaugh 7d9f55da11 feat(compiler-cli): scope type-checking of keyed defer blocks
Enforces that components, directives, and pipes in @Component.deferredImports mapped to specific block keys are only used within their designated @defer blocks during template type checking, reporting out-of-band diagnostics when used eagerly or across mismatched blocks.
2026-08-21 11:14:47 -07:00
Alex Rickabaugh b06ff75370 refactor(compiler): support block-specific deferredImports mapping
Allow `@Component.deferredImports` to be an object mapping block names to arrays of dependencies, and support `@defer (name blockName)` syntax to configure block-specific dependency lists in both standard and local compilation modes.

This enables more targeted dependency chunk generation during local compilation instead of over-eagerly loading all deferred imports together.
2026-08-21 11:14:47 -07:00
Doug Parker d609cf6e09 release: bump Angular DevTools version to 1.20.0 2026-08-19 13:22:03 -07:00
Jessica Janiuk 0e8a225f59 release: cut the v22.2.0-next.3 release 2026-08-19 13:18:44 -07:00
Jessica Janiuk 054bc6bc5c docs: release notes for the v22.1.3 release 2026-08-19 13:12:07 -07:00
Jessica Janiuk b7079c590c docs: release notes for the v20.3.29 release 2026-08-19 13:00:49 -07:00
Jessica Janiuk 1dca0588df docs: release notes for the v21.2.21 release 2026-08-19 12:54:15 -07:00
Doug Parker e041f9483e refactor(core): pass AbortSignal to WebMCP tools to handle cancellation
This forwards the `AbortSignal` natively supplied by Chrome 153.0.8009.0's update to `registerTool` executions down into the Angular context. This helps tools gracefully handle execution cancellations initiated by agents or users, preventing unnecessary background work and leaking resources.

We combine the injector/component destruction abort signals with the native WebMCP execution cancellation signals so the underlying tools correctly cancel long-running requests without producing invalid states.

Justification:
https://groups.google.com/a/chromium.org/g/chrome-ai-dev-preview/c/9291sjhIRz0/m/RFuyRrs5AAAJ
2026-08-19 12:41:09 -07:00
Angular Robot 1fb3b58abe build: update cross-repo angular dependencies to v22.2.0-next.2
See associated pull request for more information.
2026-08-19 12:38:52 -07:00
SkyZeroZx 7e39b4aedb docs: update signal forms skill to match the current implementation 2026-08-19 11:07:46 -07:00
Andrew Scott 80a04eba52 refactor(router): add support for non-blocking router resources (#70211)
Introduces support for route-level resources via the `resources` property on route definitions, enabled with `withRouterResources()`.

Router resources provide a reactive, signal-based alternative to resolvers, allowing routes to declare resources tied to route parameters and route lifecycle:
- The `resources` function executes during navigation transitions within an injection context scoped to the route (`_localInjector`).
- It receives a `ResourceContext` containing signals for `params`, `queryParams`, `fragment`, and `data`, alongside the static `snapshot`.
- For newly created routes, `resources` runs once and attaches to `ActivatedRoute.resources`. For reused routes, parameter signals update reactively to trigger new data fetches while keeping resource references stable.
- Wrapped resources (`routerResource`) provide transactional stability: snapshots are frozen during active navigations to prevent UI jitter, unfreezing on `NavigationEnd`.
- On cancelled navigations or errors, rollback recovery retains the frozen snapshot until reverted signals settle, avoiding flashes of loading state. Manual reloads are rejected while frozen.
- Local injectors are automatically cleaned up if navigations are cancelled or rolled back.

Note that this commit only implements non-blocking resources (marked with `nonBlocking()`), deferring blocking resource resolution to future work to keep the initial changeset smaller and less complex.

PR Close #70211
2026-08-19 15:28:08 +00:00
Andrew Scott 99c0f593c4 refactor(router): rename activated route injector feature to resource feature (#70211)
Activated Route Injector feature was developed for resources. This moves the internal
naming (files and vars) to reflect this now that we have landed the core bits of plumbing
and are ready to implement router resources.

PR Close #70211
2026-08-19 15:28:08 +00:00
Kam f35a3961c4 fix(docs-infra): remove stray tokens from adev illustrations
`routing.svg` and `directives.svg` each carry leftover text after a
`stroke-miterlimit` attribute, which has made them invalid XML since the
angular.dev import. They render only because decorative headers inline
them into the page, where the HTML parser turns the leftovers into empty
attributes, but the files fail anywhere they are parsed as XML,
including when served directly as `image/svg+xml`.

Neither drops anything from the drawing. The `directives.svg` leftover
repeats a path the file already declares.
2026-08-19 08:26:30 -07:00
hawkgs 023a63df8c refactor(devtools): unsubs from profiler when the perf track is disabled
Avoid the leak by unsubscribing from the profiler when the performance track is disabled.
Additionally, drop the duplicated performance track state flag.
2026-08-19 08:26:01 -07:00
Matthieu Riegler c819880b91 fix(forms): report forbidden 2way bindings on when FormField is applied
We were already reporting regular bindings but not 2way.

fixes #70219
2026-08-18 17:08:02 -07:00
Jessica Janiuk da9f3e2118 Revert "fix(compiler): preserve &ngsp; between sibling control flow blocks"
This reverts commit 53fc371142.
2026-08-18 17:03:06 -07:00
arturovt 53fc371142 fix(compiler): preserve &ngsp; between sibling control flow blocks
`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 `&nbsp;`) 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
2026-08-18 15:52:42 -07:00
arturovt c2b14b7ab4 fix(core): prevent orphaned requestIdleCallback handle from re-entrant scheduling
Defer blocks that ask to run during browser idle time with the same
options get grouped into one batch ("bucket") and processed together
the next time the browser is idle. While that batch runs, if one
callback (or the change-detection check right after it) asks to
schedule more idle work for that same batch, Angular used to register
a second idle-callback handle instead of reusing the one already in
flight.

That second handle became orphaned. By the time the batch finished
running, its queue was empty, so Angular threw away the bookkeeping
for it — including the only reference that could have cancelled the
handle. If the app was destroyed before the browser got around to
calling it, it fired anyway, against a scheduler that no longer
existed.

The root cause was a marker (idleId) that IdleScheduler uses to know
"I already have a browser callback pending for this batch, don't
request another one." That marker was being cleared to null right at
the start of processing a batch, before any of its callbacks had
actually run. So a callback that re-entrantly asked to schedule more
work mid-batch saw "nothing pending" and requested a redundant handle.

The fix: leave the marker set for the entire batch instead of clearing
it up front. Only clear it once every callback in the batch has run —
at that point, if there's leftover work, it's safe to request a fresh
handle for it.

Added a test for the basic re-entrant scenario, plus five more for
edge cases: a re-entrant add() into a different batch, and re-entrant
remove() of a sibling callback that hasn't run yet versus one that
already has.
2026-08-18 15:52:07 -07:00
Aleksander Bodurri 0ddbc47e7f fix(core): expose debuggableFn for non-computed signal graph nodes
Before: getSignalGraph only exposed debuggableFn on computed and template
nodes, preventing DevTools from linking to source code for other node types.

After: debuggableFn is also populated for linkedSignal, effect, and
afterRenderEffectPhase nodes.
2026-08-18 15:51:26 -07:00
Sam Severance bb1274d6ac fix(docs-infra): refactor unit test
Replace two toContain assertions with a single toMatch
using a multiline regex, per reviewer suggestion.
2026-08-18 15:45:30 -07:00
Sam Severance 7febf40e0d fix(docs-infra): fix code block deindentation in docs-code and docs-code-block
Consolidates deindentation logic into formatCode so both docs-code and
docs-code-block are covered by a single fix. The original deindent
function incorrectly iterated over blank lines instead of non-blank
lines when computing minimum indentation, causing code blocks to render
with excessive leading whitespace. Also fixes region extraction which
had the same trim-before-deindent ordering issue.
2026-08-18 15:45:30 -07:00
arturovt f1a4c85212 fix(router): pass correct component to canDeactivate for named outlets in componentless parent routes
When a componentless parent route has children rendered into a named outlet
(e.g. `outlet: 'inner'`), the `canDeactivate` guard received `null` as the
component argument instead of the actual component instance.

The bug was in `deactivateRouteAndItsChildren`: for componentless routes,
each child was passed the same `context` inherited from the parent lookup,
which was `null` when the parent component only registered a named outlet.
The children's actual outlet contexts were never consulted.

The fix adds a `parentContexts: ChildrenOutletContexts | null` parameter so
that for componentless routes, each child is looked up by its own outlet name
in `parentContexts` (e.g. `parentContexts.getContext('inner')`). For
component routes, `context.children` is passed as the new `parentContexts`
on recursion, ensuring correct context resolution across component boundaries.

This re-addresses #34614. A previous fix (#36302) was reverted because it
passed `parentContexts` unchanged through component boundaries; this fix
updates `parentContexts` to `context.children` when descending into a
component route, preventing the wrong contexts from propagating into deeper
componentless levels.

Fixes #34614
2026-08-18 15:04:56 -07:00
brysonbw 2720362818 feat(router): add containsTree as public API
Export containsTree from @angular/router to enable direct UrlTree subset matching.
2026-08-18 12:08:17 -07:00
Matthieu Riegler d364c83c44 ci: exclude markdown files from requiring dev-infra review
613c51e wasn't enough to exclude dev-infra
2026-08-18 09:38:45 -07:00
Kristiyan Kostadinov 732e505018 fix(core): replace all hasOwnProperty usages with Object.hasOwn
We keep getting PRs that target single usages of `hasOwnProperty` and we have ~100 of them. These changes aim to address the issue centrally by swapping out all the instances and adding a lint rule against introducing new ones.
2026-08-18 09:17:18 -07:00
Angular Robot 48a0fd6e8a feat(compiler): allow template to access private props
To allow this we'll catch the errors during typechecking and discard it.

As context, when setting `isolatedDeclarations: true` this requires developers to explicitly type every property but the `private` ones. By allowing private properties to be used in templates we discard the actually for explicit typing for template only properties.
2026-08-18 09:01:25 -07:00
arturovt c658d73210 fix(core): stop running further effects once one destroys the view mid-flush
When a view has more than one effect scheduled to run, and one of them
destroys the view (e.g. by calling `componentRef.destroy()`), the
remaining effects in that same flush could still run afterward,
against a view that no longer exists. In some cases this crashed
outright with `TypeError: view[EFFECTS] is not iterable`.

Here's why: `runEffectsInView` walks a view's effects in a `for...of`
loop, wrapped in an outer `while` loop that re-checks for any effects
that became dirty as a side effect of ones that already ran. When an
effect destroys its view, `view[EFFECTS]` gets set to `null` as part
of tearing the view down.

First attempt checked for that inside the `for...of` loop, before each
effect runs. That covers a sibling effect later in the *same* pass,
but misses a second case: if the effect that destroys the view *also*
dirties another effect on that same view in the process (e.g. by
writing a signal the sibling depends on), the outer `while` loop sees
`HasChildViewsToRefresh` set and tries to restart — and immediately
crashes re-entering `for (const effect of view[EFFECTS])` on a
now-null value, before the in-loop check ever gets a chance to run.

Reproduced that exact crash with a test first: two effects on one
view, the second one writes a signal the first depends on and then
destroys the view in the same call — confirmed it throws before
touching the fix.

Fixed by checking right after `effect.run()` instead of before it,
covering both cases in one place: the remaining effects in the current
pass, and the loop trying to restart afterward. As soon as one effect
destroys the view, nothing else runs against it again.

This is intentionally narrow in scope. An earlier version of this fix
also tried to guarantee that `onCleanup()` callbacks still ran even
when registered after an effect destroyed its own view. That's been
dropped — destroying your own view and then continuing to register
more work for it isn't something the framework should have to paper
over. If you need to do both, register `onCleanup` first, then
destroy.
2026-08-18 08:59:13 -07:00
aminesbdev 560d3f0412 docs: update naming-conventions skill 2026-08-18 08:58:44 -07:00
Alon Mishne 292991e2df Revert "fix(router): limit protocol-relative URL handling to serialization"
This reverts commit 435f8b2b8b.
2026-08-18 08:58:13 -07:00
Angular Robot 48831fc5fe build: lock file maintenance
See associated pull request for more information.
2026-08-18 08:54:49 -07:00
Matthieu Riegler 613c51e324 ci: add local skills to the fw-general scope
They were caught by dev-infra which isn't the best scope for the imho
2026-08-18 08:54:16 -07:00
arturovt 46d2cb7ff0 fix(common): preserve literal key union in KeyValuePipe.transform()
Previously, when you passed an object typed like
Record<'a' | 'b', number> into the `keyvalue` pipe, TypeScript would
"forget" that the keys could only ever be 'a' or 'b', and just tell
you the key was a plain `string` instead. So code like this used to
fail to compile, even though it's correct:

```ts
  const input: Record<'a' | 'b', number> = {a: 1, b: 2};
  const result = pipe.transform(input);
  const key: 'a' | 'b' = result[0].key; // error: string is not 'a' | 'b'
```

This happened because the pipe has multiple overloaded versions of
transform(), and TypeScript checks them top to bottom, using the
first one that matches. The "number keys" overload was listed first,
and it happened to also match string-keyed objects by accident, so
it "won" before the correct "string keys" overload ever got a
chance to run.

The fix just reorders those two overloads so the string-keys one is
checked first. Nothing about runtime behavior changes — objects with
actual numeric keys (e.g. Record<1 | 2, string>) still correctly
report their keys as plain `string`, matching what Object.keys()
really returns at runtime.
2026-08-17 15:01:24 -07:00
Jaime Burgos 6f9a6bea50 fix(platform-browser): disallow event handler attributes in Meta
Prevent arbitrary MetaDefinition properties from writing on* handlers directly to meta elements. Browser events can execute these handlers, including on meta elements rendered in the document body.
2026-08-17 14:59:50 -07:00
Shayan 3f8d9d6ea6 fix(language-server): recover project for external templates in solution-style workspaces
In a composite/solution-style workspace (e.g. an Nx monorepo, where an
app's tsconfig.json only contains project references), TypeScript can
never resolve a config file for an HTML file, since HTML files are not
listed in any referenced project. angular/vscode-ng-language-service#2165
worked around this in onDidOpenTextDocument by briefly opening the
sibling TS file so the right project loads when a template is opened
first.

However, getDefaultProjectForScriptInfo - the recovery path used by
getLSAndScriptInfo and onDidChangeTextDocument when a script info has no
configured project - did not receive the same workaround. When an open
template loses its project association (e.g. its component file is
closed and the project graph updates), every subsequent request on the
template fails with "No config file" and returns null indefinitely,
until the user manually reopens the component file.

Apply the same sibling-TS best effort in getDefaultProjectForScriptInfo,
and additionally attach the template's script info to the configured
project of its component when the config lookup still comes back empty
(openClientFile does not repeat the config lookup for already-open
files).

Also skip the sibling lookup when the .ts file does not exist, so
non-component HTML files (e.g. src/index.html) do not trigger an
open/close and config search that cannot succeed.

Fixes #69768
2026-08-17 14:59:02 -07:00
Nikita Barsukov 182c371d82 docs: use transformedValue in Forms | Custom Controls | Value transformation section
The "Value transformation" section taught readers to hand-roll
transformation with `linkedSignal()` and a manual parse method, even
though `@angular/forms/signals` ships `transformedValue()` for exactly
this case. Readers ended up with a weaker version of a feature the
framework already provides — notably, no parse error reporting.

Rewrite the section around `transformedValue()` and document the parts
the manual pattern could not cover: returning `{error}` from `parse` to
surface parse errors on the field's `errors()`, and `reset()` clearing
them. This also makes good on the cross-reference from the validation
guide, which pointed here for parse error details the section never
covered.

Fixes #70206

Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-08-17 14:58:14 -07:00
splincode d35c17d393 refactor: correct typos in comments, docs, and error messages
Fix misspellings found across multiple packages:

- `paramters` → `parameters` (utils.spec.ts)
- `directve` → `directive` (typecheck/context.ts)
- `subscriper` → `subscriber` (zone.js rxjs test)
- `swich` → `switch` (adev animation parser test)
- `subscribtion` → `subscription` (forms/abstract_model.ts)
- `lifecyle` → `lifecycle` (ng-devtools-backend hooks)
- `compatability` → `compatibility` (tree-visualizer.ts)
- `indentifier(s)` → `identifier(s)` (compiler-cli shared.ts, i18n_helpers.ts, declaration_only_emission_spec.ts)
- `identifer` → `identifier` (platform-browser shared_styles_host.ts)
- `prcess` → `process` (standalone-migration to-standalone.ts)
2026-08-17 14:57:04 -07:00
splincode b10021c79b refactor(localize): replace any with unknown in messages and translations utils
Replace unsafe `any` type annotations with `unknown` across the localize
utility layer to improve type safety and catch potential type errors at
compile time rather than at runtime.

Changes in `messages.ts`:
- `ParsedMessage.substitutions`: `Record<string, any>` → `Record<string, unknown>`
- `parseMessage` parameter `expressions`: `readonly any[]` → `readonly unknown[]`
- Local `substitutions` variable: `{[key: string]: any}` → `Record<string, unknown>`

Changes in `translations.ts`:
- `isMissingTranslationError` parameter: `any` → `unknown`, with proper
  narrowing (`typeof e === 'object' && e !== null`) before property access
- `MissingTranslationError.type` visibility: `private` → `readonly` to allow
  access through the narrowed `unknown` type in the type guard
- `translate` parameter and return type: `readonly any[]` → `readonly unknown[]`
- `makeTemplateObject` cast: `cooked as any` → `cooked as unknown as TemplateStringsArray`

Fix in `mock_message.ts` (test helper):
- `substitutions: []` → `substitutions: {}` — the array literal was only
  assignable because the field was typed as `any`; the correct empty value
  for a `Record<string, unknown>` is an object literal
2026-08-17 14:56:31 -07:00
arturovt 38d093232c fix(forms): warn in dev mode when ngModel cannot reach parent NgForm across component boundary
NgModel injects ControlContainer with @Host(), which stops the injector at
the component host element boundary. When NgForm lives in a parent component
and ngModel lives in a child component, the injection returns null silently
and the control acts standalone — never registering with the form.

To surface this invisible failure, emit a dev-mode warning (NG01354) when
ngModel's @Host() injection finds nothing but the element Injector can still
reach a ControlContainer further up the hierarchy. The warning identifies the
cross-boundary issue and points developers to the viewProviders fix or the
standalone option.

Adds the NG01354 reference page explaining why the warning fires and providing
two remediation paths: bridging ControlContainer via viewProviders, or opting
out with [ngModelOptions]="{standalone: true}".

Fixes #47580
2026-08-17 13:59:40 -07:00
Vincent 70b252cac3 test(core): Add test to ensure Angular correctly detects paths when served from file system
This test makes sure that when Angular is served from Electron or just from the file system that the router works correctly.
2026-08-17 13:58:54 -07:00
Jaime Burgos 45ebb127e3 refactor(compiler-cli): add error guide links to diagnostics
Add the error guide URL when a compiler diagnostic uses a negative
marked error code.
2026-08-17 13:58:11 -07:00
arshiya tabasum c73a001fbf fix(animations): detect object trigger values with Object.hasOwn
StateValue and AnimationTransitionNamespace.trigger detect the {value,
params} object form of a trigger binding by calling hasOwnProperty on the
bound value. When that value is an object from untrusted data (for example
a parsed JSON payload) carrying an own hasOwnProperty key, the shadowed
property is called as a method and throws, breaking the animation flush.
Use Object.hasOwn for the check so a shadowing key no longer matters.
2026-08-17 13:53:17 -07:00
SkyZeroZx 1a006a8f97 fix(http): cancel oversized fetch response bodies
Cancel the unread response body before reporting NG02825 when its declared Content-Length exceeds the configured buffer limit. Without cancellation, SSR can finish while the underlying connection remains open.

Add regression coverage for the declared-length rejection path.
2026-08-17 13:52:12 -07:00
Matthieu Riegler ed3373868d refactor(language-service): adapt strict template suggestion
In v22, `strictTemplates` is true by default. We need to adapte the LS to online report the suggestion when the option is explicitly `false`
2026-08-17 13:51:43 -07:00
Kam 064530447e feat(docs-infra): add Angie to the routing illustration
The routing header draws a serpentine route with map pins on it but
nobody travelling it. Angie now stands on the top segment, the same way
she stands on the road in the roadmap header.

She needs more headroom than the canvas had, so the viewBox gains 12
units at the top and the illustration carries its own max-height, which
keeps the rest of the drawing at the size it rendered before.
2026-08-17 13:46:46 -07:00
SkyZeroZx 3e7094b049 docs: correct Angular developer skill guidance 2026-08-17 13:44:50 -07:00
Evgenii Fomin 8d6c6a9a0c docs: make a note regarding i18n messageIdFormat 2026-08-17 13:44:22 -07:00
Kam 1c2b0575ed feat(docs-infra): add Angie to the roadmap illustration
The roadmap header draws a road between a start pin and a destination
pin, but nothing travels it. Angie already appears on the 404 page, the
embedded editor states and the error snack bar, so put her on the road
too.

Decorative headers are inlined into the page so the road can use CSS
variables for dark mode, which means the pose has to be embedded as
paths, with its classes flattened and its ids prefixed to keep them out
of document scope.

Note this asset is also the essentials Next Steps header.
2026-08-17 13:33:29 -07:00
hawkgs 9711e86f2a refactor(devtools): collapse injected services section in the side pane by default
Collapse the section since it takes a significant portion of the vertical space,
whereas most of the times users are exploring the properties leading them to scroll.

Addiotionally, introduce some other minor UI improvements.
2026-08-17 13:30:46 -07:00
hawkgs f746463caa fix(devtools): breadcrumbs missing nav arrows
Show the missing nav arrows when you select a deeply nested component where
the breadcrumbs path is longer than the container. The nav arrows used to
appear only when the split is resized. Add some other minor improvements.
2026-08-17 13:29:05 -07:00
Aleksander Bodurri 2a2585708a fix(devtools): clarify disabled View Source tooltip and update demo app
Before: The View Source button tooltip in signal details static ('View source') even when disabled.

After: The tooltip explains 'Source location is not available for this node' when disabled.
2026-08-17 13:28:27 -07:00
Aleksander Bodurri a1fd3c45f9 fix(core): expose debuggableFn for non-computed signal graph nodes
Before: getSignalGraph only exposed debuggableFn on computed and template
nodes, preventing DevTools from linking to source code for other node types.

After: debuggableFn is also populated for linkedSignal, effect, and
afterRenderEffectPhase nodes.
2026-08-17 13:28:27 -07:00
SkyZeroZx ea3097c774 docs: add example for conditional redirects in routing 2026-08-17 13:26:49 -07:00
Angular Robot 544d084c34 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-08-17 13:24:20 -07:00
Angular Robot 5980138246 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-08-17 11:27:16 -07:00
hello 789c9c242d docs: update Angular MCP skill reference 2026-08-17 10:43:11 -07:00
Matthieu Riegler 28f323a578 ci: update github nick
ethan changed his nick, this was causing some pullapproves errors when a pr hit the primitives-shared scope.
2026-08-17 10:40:39 -07:00
Aleksander Bodurri a3a7764975 fix(devtools): prevent duplicate highlightComponent listener in injector tree
Move the message bus subscription out of afterRenderEffect into constructor initialization and clean up the listener on destroy using DestroyRef.
2026-08-17 10:37:40 -07:00
Angular Robot 3afe9e6fa3 build: update pnpm to v11.22.0
See associated pull request for more information.
2026-08-17 10:35:40 -07:00
Angular Robot ec678c0f8d build: update dependency ng-packagr to v22.2.0-next.3
See associated pull request for more information.
2026-08-14 09:29:45 -07:00
arturovt c6e4a36be1 fix(core): throw a descriptive error instead of crashing when a hydration node is missing
locateOrCreateElementNodeImpl looks up the DOM node for an element
during hydration and immediately checks its nodeType. If the
client-rendered DOM has fewer nodes than the server-rendered HTML,
the lookup returns null, and in production that null flows straight
into the nodeType check and crashes with a raw, uncoded
"Cannot read properties of null (reading 'nodeType')" TypeError.

The dev-mode check that would normally catch this (validateMatchingNode)
already handles a missing node, but it's compiled out of production
builds, so the crash only shows up outside of dev mode.

Add a null check ahead of the nodeType check that throws a coded
RuntimeError using the existing HYDRATION_MISSING_NODE (NG0502) code,
with a descriptive message in dev mode and a cheap fallback in
production. Also add a regression test that removes a server-rendered
element before hydration runs and asserts a coded RuntimeError is
thrown instead of a raw TypeError.
2026-08-14 08:30:49 -07:00
arturovt 1cb3d606bf fix(platform-browser): throw a descriptive error when insertBefore reference node is missing
Angular's internal LView/TNode bookkeeping can get out of sync with the
real DOM: manual DOM manipulation, a browser extension, or an edge case in
Angular's own view-insertion/reordering code can all leave Angular believing
a node is still attached at a given position when it isn't. The next time
Angular's renderer calls `insertBefore` relative to that stale reference
node, the native DOM API throws an opaque `NotFoundError` with no indication
of which node or component was involved, making these errors effectively
undebuggable in production:

    NotFoundError: Failed to execute 'insertBefore' on 'Node': The node
    before which the new node is to be inserted is not a child of this node.
        at Node.insertBefore (native)
        at DefaultDomRenderer2.insertBefore (packages/platform-browser/src/dom/dom_renderer.ts)
        at nativeInsertBefore (packages/core/src/render3/dom_node_manipulation.ts)
        at nativeAppendOrInsertBefore (packages/core/src/render3/dom_node_manipulation.ts)
        ... (called while Angular inserts or moves a view during change detection)

Check the reference node's actual parent against the expected parent before
calling the native `insertBefore`, and throw a descriptive `RuntimeError`
(NG05106) instead, following the same pattern already used for hydration
node mismatches.
2026-08-14 08:29:59 -07:00
Edu 12b0acd498 feat(devtools): implement persistent breakpoints on signal consumers using CDP
Implements persistent breakpoints for Angular signal consumers (computeds and effects) in Angular DevTools using Chrome DevTools Protocol (CDP).

- Adds debugger permission to Chrome and Firefox extension manifests.
- Implements CDP breakpoint orchestration in background script.
- Updates SignalDetailsComponent and SignalGraphPaneComponent with label icon toggle and persistent state sync across reloads.
2026-08-14 08:26:55 -07:00
Edu 6bfbfcc3a1 refactor(core): expose debuggableFn for effects in signal debug graph
Exposes the internal fn reference of effect reactive nodes on DebugSignalGraphNode as debuggableFn. This allows Angular DevTools to inspect and set breakpoints on effect callbacks.
2026-08-14 08:26:55 -07:00
Kristiyan Kostadinov 262fba7f7d build: resolve CI failures
Resolves some e2e failures that only happened on CI.
2026-08-14 08:22:34 -07:00
Kristiyan Kostadinov 7b74bee5b4 build: switch adev tests away from protractor
Reworks the tests in adev not to depend on Protractor.
2026-08-14 08:22:34 -07:00
Kristiyan Kostadinov 204265f9a3 build: switch examples away from protractor
Reworks the `examples` tests not to depend on Protractor.
2026-08-14 08:22:34 -07:00
Kristiyan Kostadinov 413c79c10b build: switch core tests away from protractor
Reworks the tests under `core` not to depend on Protractor.
2026-08-14 08:22:34 -07:00
Kristiyan Kostadinov 3d43067e20 build: switch playground away from protractor
Reworks the `playground` tests not to depend on Protractor.
2026-08-14 08:22:34 -07:00
Kristiyan Kostadinov 4d2dc1fb08 build: add webdriver build rule
Sets up a build rule to use Selenium Webdriver for e2e tests.
2026-08-14 08:22:34 -07:00
Angular Robot 6c6141b0ad build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-14 08:20:48 -07:00
Angular Robot d3d3bc62ea build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-13 13:35:29 -07:00
Jaime Burgos ba13a3ce22 fix(vscode-extension): prevent command URI injection in TSDK approval
VS Code parses notification text for links and permits `command:` URIs. Interpolating the workspace-controlled TSDK path can therefore let a malicious path add a command link to the approval prompt.

Remove the path from the notification instead of attempting to sanitize or escape it. This keeps the prompt static and matches VS Code's TypeScript extension workspace-version approval flow.

Fixes #70176
2026-08-13 13:34:36 -07:00
Aristeidis Bampakos 144b90c907 docs: add code style in Antigravity file reference 2026-08-13 13:33:41 -07:00
Alex Rickabaugh dc65e3656f fix(core): accept readonly arrays for setClassMetadata decorators
When reflection metadata is emitted via setClassMetadata, passing readonly arrays or const tuples for the decorators parameter causes TypeScript type checking errors because setClassMetadata previously expected decorators to be a mutable any[] or null.

This change updates the setClassMetadata type signature to accept decorators as readonly any[] or null and casts the parameter internally when mutating the class metadata property.
2026-08-13 13:33:07 -07:00
Alex Rickabaugh eee9ef4d09 fix(core): allow readonly arrays in RawScopeInfoFromDecorator
When components pass  arrays or readonly tuples to decorator metadata fields (such as ), typechecking generated decorator reflection metadata causes a TS2322 type mismatch error because  previously only accepted mutable .

This change updates  to accept , allowing  arrays and readonly tuples to be assigned without TypeScript compilation errors.
2026-08-13 13:33:07 -07:00
arturovt 4560f4fdcd fix(core): throw NG0500 instead of a raw TypeError on element hydration mismatch
When hydration locates the DOM node for an ɵɵelementStart/ɵɵdomElementStart
instruction, locateOrCreateElementNodeImpl assumed the located node was
always an Element and called hasSkipHydrationAttrOnRElement(native), which
does native.hasAttribute(...). The check that would normally catch this
class of mismatch, validateMatchingNode, is gated behind `ngDevMode &&` and
is compiled out of production builds. So when a real SSR/hydration
structural mismatch located a Text or Comment node instead of the expected
Element, production builds hit .hasAttribute on a node type that doesn't
have it and crashed with a raw, uncoded TypeError instead of a coded
hydration-mismatch RuntimeError.

Add a cheap, always-on nodeType check ahead of that call. On mismatch it
throws RuntimeError(HYDRATION_NODE_MISMATCH, ngDevMode && '...'), the same
pattern used elsewhere in the codebase, so the descriptive message is only
built in dev mode and production keeps throwing just the bare NG0500 code
without pulling validateMatchingNode's DOM-printing machinery into the
production bundle (verified via the bundling/hydration golden-symbols test,
which is unchanged).
2026-08-13 13:32:34 -07:00
Alon Mishne 5ed071d39d docs: release notes for the v22.1.2 release 2026-08-13 12:05:55 -07:00
Alon Mishne 40d23fa3ff release: cut the v22.2.0-next.2 release 2026-08-13 11:46:28 -07:00
Alon Mishne 044e69c1c4 docs: release notes for the v20.3.28 release 2026-08-13 10:14:06 -07:00
Angular Robot 16e42c39c1 build: update all non-major dependencies
See associated pull request for more information.
2026-08-13 09:05:24 -07:00
Bhuvansh855 647bf8e143 docs: note SafeResourceUrl audio src change 2026-08-13 08:55:03 -07:00
Angular Robot ab38005c6e build: update dependency node to v24
See associated pull request for more information.
2026-08-13 08:50:41 -07:00
Andrew Scott 6f848db435 build(vscode-extension): dynamically resolve upstream remote and use token for https pushes
Previously, the release script hardcoded the upstream repository URL as an unauthenticated HTTPS URL (https://github.com/angular/angular.git). Although the script verified that a GITHUB_TOKEN environment variable was present, it only used that token for REST API calls (such as creating the GitHub release) and did not provide it to Git commands. As a result, users who authenticate to GitHub via SSH (and do not have an HTTPS Git credential helper configured) were prompted interactively for GitHub login credentials when pushing the release tag.

This change dynamically resolves the upstream remote name from the user's configured remotes by checking for any remote pointing to angular/angular. When pushing over SSH, Git uses the user's existing SSH credentials. When pushing over HTTPS (or falling back), the script injects GITHUB_TOKEN into the push URL to prevent interactive authentication prompts.
2026-08-13 08:38:53 -07:00
Angular Robot e6be990f77 build: update all github actions
See associated pull request for more information.
2026-08-13 08:36:30 -07:00
Angular Robot 3002a24192 build: update dependency tar.bzl to v0.10.8
See associated pull request for more information.
2026-08-13 08:34:12 -07:00
Angular Robot b7ed8d81ac build: lock file maintenance
See associated pull request for more information.
2026-08-13 08:28:25 -07:00
Alon Mishne c9990c4354 docs: release notes for the v21.2.20 release 2026-08-12 17:08:53 -07:00
Angular Robot bf1f63476d build: update cross-repo angular dependencies to v22.2.0-next.1
See associated pull request for more information.
2026-08-12 16:13:42 -07:00
Angular Robot da8b7de52a build: update pnpm to v11.21.0
See associated pull request for more information.
2026-08-12 16:13:06 -07:00
Andrew Scott e8aa222e7d fix(compiler-cli): correctly resolve symbol for SafePropertyRead in chained optional navigation
When resolving template symbols for SafePropertyRead in TCBs emitted with optional chaining (strictSafeNavigationTypes: true), SymbolBuilder falls back to finding a TS node matching the AST expression's nameSpan. It then traverses up through parent nodes to find the enclosing expression.

Previously, the traversal loop checked isAccessExpression(node.parent) without verifying whether node was the accessed member name or the expression receiver. When multiple optional navigation expressions are chained (e.g. route?.data?.['icon']), the parent of ((route)?.data) is an access expression where ((route)?.data) is the receiver. Because isAccessExpression was true, the loop continued ascending into the outer access expression, causing symbol resolution for data to erroneously return the symbol and TCB location of icon.

This commit refines the parent traversal condition so that it only climbs into a parent PropertyAccessExpression if node is the accessed name (node.parent.name === node), preventing escape into outer receiver expressions.
2026-08-12 16:11:23 -07:00
SkyZeroZx a26fbfa641 refactor(core): distinguish animations that share a name
animate.leave waits for the longest-running animation before removing an element. When multiple animations use the same keyframe name, their animationend events have the same animationName, so a shorter animation can be mistaken for the longest one and remove the element too early.

Track the longest animation duration returned by getAnimations() and compare it with the duration from event.animation when available. Keep the existing name/property checks as a fallback for older browsers and computed-style detection.

Allow a 1ms tolerance for rounding differences between CSSOM and Web Animations and add a regression test using values equivalent to fractional calc() durations.
2026-08-12 16:09:27 -07:00
Andrew Scott c111f3fb0c refactor(router): Create transactional router resource
This commit adds an implementation of a router resource (not currently exposed for public use) which
defines the behavior of a resource dependent on the Router navigation lifecycle.
2026-08-12 16:07:05 -07:00
Andrew Scott e53bb2bca7 release: bump VSCode extension version to 22.1.0 (#70171) (#70172)
Co-authored-by: Alon Mishne <3197814+amishne@users.noreply.github.com>
Co-authored-by: Alon Mishne <amishne@users.noreply.github.com>
2026-08-12 16:05:05 -07:00
Doug Parker 9810a3e33c release: bump Angular DevTools version to 1.19.1 2026-08-12 19:47:21 +00:00
Jessica Janiuk 3d32db6a49 docs: clarify animate.leave child animation behavior
This updates the docs to be explicit about `animate.leave` and nested element removal order. It clearly specifies that `animate.leave` will only fire nested animations within the same component template.

closes: #70131
2026-08-12 11:07:14 -07:00
SkyZeroZx 870a525bd3 test(platform-server): clean up viewport hydration observer
Trigger routed viewport hydration so its cached observer is removed before later randomized specs run.
2026-08-12 11:04:40 -07:00
Matthieu Riegler f1c0c405c9 refactor(compiler): remove explicit strict: true
This flag is set by default in TS 6.0
2026-08-12 11:03:53 -07:00
SkyZeroZx 435f8b2b8b fix(router): limit protocol-relative URL handling to serialization
Preserve createUrlTree command semantics, including custom serializer inputs, while keeping the single-leading-slash guarantee at the default serialization boundary.

Expand coverage for command forms, public UrlTree values, secondary outlets, and preserved query parameters and fragments.

Fixes #69700
2026-08-11 12:07:31 -07:00
Andrew Scott b65dea4f03 feat(router): allow throwing RedirectCommand to trigger redirects
This allows developers to throw a `RedirectCommand` directly from guards and resolvers to trigger a redirect.

The primary benefit is that we no longer need to pollute the return type of functions that redirect. For example, a deeply nested helper function or a resolver can now simply throw a `RedirectCommand` to short-circuit and redirect, instead of having to return the `UrlTree` or `RedirectCommand` all the way up the call stack.

This aligns with prior art in other modern framework routers (such as Next.js, Remix, and SvelteKit), which commonly use thrown exceptions or special redirect responses to abort execution and trigger immediate redirection.
2026-08-11 10:03:43 -07:00
Kam dd29713828 fix(docs-infra): contain scroll within adev dropdown menus
Scrolling to the top or bottom of a dropdown let the scroll event chain into
the page behind it, causing the whole app to scroll. #70137 fixed this for the
version picker, but the same containment was missing on every other menu.

The API reference filter, the tutorial step list and the update guide's version
dropdowns already had a scroll container, so they only needed
overscroll-behavior.

The social and theme mini-menus had neither a height cap nor overflow, so
overscroll-behavior alone would have been inert on them. They now share the
version picker's max-height/overflow-y/overscroll-behavior, hoisted onto
.adev-mini-menu, which also keeps their items reachable when the viewport is
too short to fit the whole menu.
2026-08-11 10:00:53 -07:00
Georgi Serev 66c5ea7544 refactor(devtools): improve profiler ux
- Add info tooltips that describe the visualizations and other
parts of the UI
- Improve the frame selector by adding axes labels and a
horizontal line for frames exceeding 60 fps
- Use a precise frame rate calculations instead of approximations
- Introduce improvements to the details panel
- Improve the bar chart visualization
- And more
2026-08-11 10:00:02 -07:00
Alex Rickabaugh 8925a4ee49 fix(core): ensure i18n_util hasOwnProperty checks are safe for property renaming
`getTIcu` and `setTIcu` performed `hasOwnProperty` checks with string
literals (`'currentCaseLViewIndex'` and `'tView'`). Under Closure Compiler
property renaming optimizations, these properties are minified but the
string literals are not, causing property lookups and type discriminations
to fail.

This commit defines closure-safe property constants using
`getClosureSafeProperty` so the property names are renamed consistently.
2026-08-10 15:35:38 -07:00
splincode 8e41e97dfe docs: update Angular Aria roadmap status
Update the roadmap to reflect that Angular Aria became stable in Angular v22 while development of new patterns continues.
2026-08-10 15:34:51 -07:00
Angular Robot 4fc6e319bf build: update dependency @types/jsdom to v30
See associated pull request for more information.
2026-08-10 09:43:40 -07:00
Angular Robot 78c0cdd80d docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-08-10 09:42:52 -07:00
yamanerkam 768c8c29dc fix(docs-infra): contain scroll within version picker dropdown
Scrolling to the top or bottom of the version picker's dropdown list
let the scroll event chain into the page behind it, causing the whole
app to scroll. The search dialog and search history dropdowns already
guard against this with overscroll-behavior: contain; apply the same
fix to the version picker.
2026-08-10 09:11:18 -07:00
Angular Robot b95f9e2691 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-10 08:57:16 -07:00
Kristiyan Kostadinov 565dbb2fe5 fix(core): incorrect loop in defer blocks
Fixes that we were running a `for in` loop on an array and silently doing the wrong thing.

Fixes #70113.
2026-08-07 16:35:03 -07:00
Ady Elouej 107f6fa49d fix(compiler): remove namespaced MathML script elements
Treat MathML-namespaced script elements as scripts during template preprocessing. This prevents scripts nested in MathML HTML integration points from surviving template compilation.
2026-08-07 16:32:57 -07:00
Matthieu Riegler 03f1758e2a fix(devtools): fix regression for node serialization.
This fixes a regression introduced by #69309 where the format of `serializedId` from a coma separated string, to a JSON representation of an array.

fixes #70104
2026-08-07 16:30:22 -07:00
SkyZeroZx 4631a6e479 refactor(forms): modernize Signal Forms tests
replace change detection calls with whenStable for async tests
2026-08-07 16:22:59 -07:00
Ady Elouej 9f8e32616b fix(core): reject prefixed SVG script hosts
Use the host element's namespace-aware local name when checking for script
elements. A prefixed SVG script can expose a qualified tag name such as
"x:script" while its local name remains "script".
2026-08-07 16:19:13 -07:00
SkyZeroZx ec372d6029 refactor(platform-browser): modernize DOM renderer tests
Migrate fixtures to standalone components and await zoneless updates
2026-08-07 16:17:19 -07:00
splincode 9e37a58e14 fix(forms): keep radio inputs in sync when values change
Recompute the checked state when a reused radio input receives a new value while the form model remains unchanged.

Handle this case for both reactive forms and signal forms, and add regression tests covering reused radio elements.
2026-08-07 16:15:06 -07:00
Kristiyan Kostadinov 11b4089acf test(compiler): add test for imports with unquoted URL
Adds a test to cover the case where an `@import` might have a URL with special characters that isn't quoted.
2026-08-07 16:12:51 -07:00
Kristiyan Kostadinov a4f1a94948 fix(compiler): do not encapsulate nested selectors if parent contains ::ng-deep
Updates the nested selector encapsulation logic so that it skips encapsulating child selectors if the parent contains `::ng-deep`. The reasoning is that `:host ::ng-deep { .foo {} }` should behave as `:host ::ng-deep .foo {}`.
2026-08-07 16:12:51 -07:00
Kristiyan Kostadinov d0d7f57e08 fix(compiler): scope nested CSS rules
This is a second attempt at scoping nested CSS rules after not being able to land #50693. I took some extra precautions to try and avoid the crash that was happening last time.
2026-08-07 16:12:51 -07:00
Matthew Beck 8d6c925392 fix(compiler-cli): record class extends clause references in DeferredSymbolTracker
`DeferredSymbolTracker.lookupIdentifiersInSourceFile` prunes `ts.isTypeNode`
subtrees so that references appearing exclusively inside type annotations
do not keep static import declarations in the emitted JavaScript.

However, `ts.isTypeNode` returns `true` for `ts.ExpressionWithTypeArguments`,
which TypeScript uses to represent both `extends` and `implements` heritage
clauses. An `extends` clause on a class declaration or class expression is a
value position that survives in the emitted JavaScript output.

Because `isTypeNode` returned `true`, references to base classes imported
alongside deferred dependencies were ignored. As a result, the compiler
erroneously marked the static import statement as deferrable and deleted it
from the emitted JavaScript, leaving the `extends <Base>` clause referencing
an undeclared identifier and causing a runtime `ReferenceError`.

This commit ensures that `ExpressionWithTypeArguments` under a class `extends`
clause is not treated as an erasable type node, preserving the static import
whenever a base class is referenced.
2026-08-07 16:10:41 -07:00
Angular Robot adb770bd20 build: update bazel dependencies
See associated pull request for more information.
2026-08-07 16:03:52 -07:00
Angular Robot 0f0058900c build: update all github actions
See associated pull request for more information.
2026-08-07 16:02:04 -07:00
Angular Robot 6b1fd3463c build: update pnpm to v11.20.0
See associated pull request for more information.
2026-08-07 15:59:00 -07:00
Angular Robot 0eaf1c55d3 build: update all non-major dependencies
See associated pull request for more information.
2026-08-07 15:56:00 -07:00
Matthieu Riegler d7b03f5523 fix(compiler): Generate correct expression for optional chaning.
Optional chaining was generating expressions with included an extra pair of parenthesis which changed the semantics of the expression and threw an unexpected error from the optional chain non nullable extended diagnostic.

fixes #70085
2026-08-07 15:55:10 -07:00
SkyZeroZx 09bc90003e fix(http): always decode JSON responses as UTF-8
Keep the charset handling added in #70062 limited to text responses. JSON
bytes must stay UTF-8 regardless of the Content-Type charset.

Fetch defines Body.json() using "parse JSON from bytes". Infra specifies that
step as: "Let string be the result of running UTF-8 decode on bytes."

https://fetch.spec.whatwg.org/#dom-body-json
https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value
2026-08-07 15:54:20 -07:00
Alan Agius cf1844bcce refactor(devtools): use JavaScriptTransformer for Angular optimization esbuild plugin
Refactor the devtools optimization esbuild plugin to use JavaScriptTransformer from @angular/build/private.
2026-08-07 10:30:52 -07:00
Alan Agius 573145afb5 refactor(devtools): remove async-await downleveling as devtools is zoneless
Remove the supported 'async-await': false option in esbuild-base.config.mts as Angular DevTools is zoneless and does not require downleveling async/await syntax.
2026-08-07 10:30:52 -07:00
Alan Agius 07f58006c5 refactor(devtools): rely on esbuild to downlevel async generators
Configure esbuild with supported 'async-await': false in esbuild-base.config.mts so esbuild downlevels async functions and async generators natively.

This allows removing the custom Babel plugin @babel/plugin-transform-async-generator-functions and downlevelAsyncGeneratorsIfPresent option.
2026-08-07 10:30:52 -07:00
Joey Perrott 8a40fbefdf release: cut the v22.2.0-next.1 release 2026-08-07 11:19:03 -06:00
Joey Perrott 165279fe3e docs: release notes for the v22.1.1 release 2026-08-07 10:13:12 -07:00
lazerg 96b80424c7 docs: fix supported Node.js version in installation prerequisites 2026-08-04 10:31:03 -07:00
Matthieu Riegler ef4dfead83 fix(http): avoid aborting completed requests in FetchBackend
Prevent AbortController.abort() from executing during Observable teardown when a FetchBackend HTTP request has already completed successfully or errored.
Previously, FetchBackend unconditionally called abort() upon stream termination. When requests completed normally, calling abort() after delivery caused Chromium-based browsers to mark the resolved request as net::ERR_ABORTED in DevTools due to a race condition, leading to missing response body payloads ("Failed to load response data"). By tracking whether the request has already settled—similar to XhrBackend checking for xhr.readyState !== xhr.DONE—we ensure abort() is only called for unsettled, in-flight requests upon unsubscription.

Fixes #70071
2026-08-04 09:37:35 -07:00
Angular Robot 308a361f71 build: update domino digest to e0779df
See associated pull request for more information.
2026-08-04 09:35:04 -07:00
SkyZeroZx 2f0be5bef8 refactor(common): modernize directive tests to rely on whenStable
Replace synchronous detectChanges calls with zoneless-compatible scheduling and stability waits in NgClass, NgStyle, and NgOptimizedImage tests.
2026-08-04 08:45:01 -07:00
Alan Agius 280d09b160 fix(http): strip RFC 6265 DQUOTE characters and handle URIError in parseCookieValue
Previously, `parseCookieValue` did not strip enclosing double quotes (`DQUOTE`) from quoted cookie values as specified in RFC 6265 Section 4.1.1. In addition, malformed percent-encoding in cookie values caused an unhandled `URIError` when calling `decodeURIComponent`.
2026-08-04 08:29:46 -07:00
Matthieu Riegler 6a0789dc7f fix(http): respect content-type charset in fetch backend text decoder
Extract the charset parameter from the Content-Type response header in FetchBackend and pass it to TextDecoder when decoding text and json responses. When no valid charset is provided or supported, gracefully fall back to default utf-8 decoding.

Fixes #70061
2026-08-04 08:28:23 -07:00
Angular Robot f68291515a build: lock file maintenance
See associated pull request for more information.
2026-08-04 08:25:59 -07:00
Shuaib Hasan Akib 337053ef1a refactor(compiler): remove unused code and exports
Removes unused code and exports that are no longer referenced anywhere
in the compiler codebase.
2026-08-03 09:42:08 -07:00
Suraj Yadav fb698d12cd test(platform-server): add SSR integration test for null and normal input values
Fixes #69785

Add an Angular SSR integration test in platform-server verifying that null input values do not render string attributes like value="null" during server-side rendering, while normal non-empty string values like value="hello" are properly preserved.
2026-08-03 09:30:45 -07:00
Kam efe1aae1cd fix(docs-infra): keep inline code in links as an atomic inline box
Inline code inside a link renders as a chip with its own background. Text
decoration propagates from the anchor and cannot be cancelled by a descendant,
so with the chip laid out as a regular inline box the link underline is drawn
straight across it.

Lay the chip out as an atomic inline box, which the propagated decoration is not
drawn across. This applies to the link rule only; code outside of links keeps
`display: inline` for wrapping in multiline paragraphs, and the link rule
already sets `white-space: nowrap`.
2026-08-03 09:20:15 -07:00
lazerg 36c2197539 fix(zone.js): guard against null handle when detecting refreshable timers
A timer wrapper such as a browser extension, policy, or automation harness can block a call and return null instead of a handle. patchTimer then read `.refresh` on that null value and threw synchronously.

Treat a nullish handle as non-refreshable so the patched timer keeps working.

Fixes #70044
2026-08-03 09:14:04 -07:00
SkyZeroZx c9c4f2afc6 refactor(common): modernize directive tests to rely on whenStable
Replace synchronous detectChanges calls with zoneless-compatible scheduling and stability waits. Preserve NgComponentOutlet coverage for components declared by NgModules.
2026-08-03 09:13:32 -07:00
Angular Robot 10244503d7 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-08-03 09:10:41 -07:00
Kam f2f12925bd docs: fix roadmap link text and preview-site link
Two link issues on the roadmap page:

- "Introduce deferred loading" linked next.angular.dev, the preview build of
  this same site, for a page that exists here at guide/templates/defer. Use the
  relative path so readers stay on the stable docs.
- "Local template variables" linked "`@let` docs", putting a code chip and a
  plain word in one anchor. The anchor's underline crosses the chip and the two
  halves render in different colors. Link only the symbol, as the rest of adev
  does.

Also on the same page:

- Drop a stray space before a period in the Components card.
- Give the older completion labels the same "Completed in <quarter>" wording the
  newer cards already use.
2026-08-03 08:58:35 -07:00
Angular Robot 4aacaecb96 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-08-03 08:55:37 -07:00
Matthieu Riegler 1b13db7a1b refactor(animations): remove outdated comment
This isn't necessary anymore.
2026-07-31 15:34:04 -07:00
SkyZeroZx cfe2cda110 fix(core): initialize hydration triggers after late runtime activation
After incremental hydration became tree-shakable, application bootstrap could finish before a routed component activated the runtime. The one-time trigger scan was then skipped, leaving routed and nested hydration triggers uninitialized.

Coordinate application bootstrap with runtime activation and initialize once both have occurred.

Fixes #69908
2026-07-31 12:26:08 -07:00
Matthieu Riegler 3a29329191 fix(devtools): Extension name for non googlers.
For corps urls the promise is actually resolved but returns a `status:0`.

fixes #70023
2026-07-31 11:18:21 -07:00
Kam 690eecda6b docs: document deprecated allowSignalWrites option in v19 update guide
The `allowSignalWrites` option of `effect()` became a no-op and was
deprecated in v19, but the update guide never mentioned it. Applications
upgrading from v18 or earlier still carry the option at their `effect()`
call sites, where it now only produces a dev-mode warning.

Add an entry to the v19 recommendations instructing those applications to
remove it, mirroring the wording of the deprecation notice on
`CreateEffectOptions`.
2026-07-31 08:39:57 -07:00
hawkgs e144e697ff refactor(devtools): substitute remaining Angie images with ng-angie
Substitute the remaining `<img>`s with the Angie component.
2026-07-31 08:36:09 -07:00
Jaime Burgos bb78286e5e fix(http): run root interceptors in the terminal request chain
Represent withRequestsMadeViaParent() with an internal delegating backend so the interceptor handler can distinguish delegated clients from independent child configurations.
2026-07-31 08:32:14 -07:00
Angular Robot 245e6f37ea build: update cross-repo angular dependencies
See associated pull request for more information.
2026-07-31 08:23:37 -07:00
Angular Robot 8496d9c2e2 build: update pnpm to v11.18.0
See associated pull request for more information.
2026-07-31 08:22:39 -07:00
Angular Robot 93b659c455 build: update dependency node to v22.23.2
See associated pull request for more information.
2026-07-31 08:21:27 -07:00
Markus Mächler a37c79d7d4 docs: remove duplicate aria-hidden attributes in aria examples 2026-07-30 15:22:14 -07:00
Kam 5dd634d18d docs: fix self-referential link and merge intro tips in inputs guide
The "Customizing model inputs" section linked "standard input" back to
the inputs guide itself, a dead-end self-link. Point the sentence at the
relevant in-page sections instead (#required-inputs and #input-aliases).

Also merge the two stacked intro TIP callouts into a single tip.
2026-07-30 15:20:41 -07:00
Angular Robot b63b9032b4 build: update all non-major dependencies
See associated pull request for more information.
2026-07-30 09:59:54 -07:00
Aristeidis Bampakos a0f943d53d docs: replace Firebase Studio references with Antigravity 2026-07-30 09:58:07 -07:00
Angular Robot 9e5dc74b67 build: update cross-repo angular dependencies
See associated pull request for more information.

Closes #69910 as a pr takeover
2026-07-30 09:41:50 -07:00
SkyZeroZx 6deb6afcd1 refactor(forms): modernize reactive forms tests to rely on whenStable
Rely on zoneless scheduling throughout reactive forms tests instead of triggering change detection manually.
2026-07-30 09:06:29 -07:00
splincode e43eb96341 fix(core): warn when style property bindings receive invalid values
Report unsupported style property binding values in development mode while preserving existing binding behavior. Unwrap trusted style values before appending unit suffixes and link NG0318 warnings to the corresponding error guide.
2026-07-30 09:05:46 -07:00
Jaime Burgos d068fc1ea0 refactor(common): modernize pipes & non bindable tests to rely on whenStable
Rely on zoneless scheduling throughout reactive forms tests instead of triggering change detection manually.
2026-07-30 08:56:25 -07:00
splincode 5d76720e06 refactor(compiler): replace any casts with precise types
- r3_factory: use `in` operator instead of `as any` property probing
  in isDelegatedFactoryMetadata / isExpressionFactoryMetadata type guards
- r3_deferred_triggers: narrow assignment to
  `DeferredBlockTriggers[typeof name]` instead of `as any`
- defer_resolve_targets / reify: drop unnecessary `as any` on
  `op.trigger` — `DeferTriggerBase.kind` is present on all union members
- pipe_creation: replace double `as any` with `as {target?: ir.XrefId}`,
  and reuse the already-narrowed `slotHandle` variable for the call
- extractor_merger: replace legacy `<any>console` guards with a proper
  `typeof console !== 'undefined'` check
2026-07-30 08:55:04 -07:00
hawkgs 5124417370 refactor(devtools): hide search button when there is not a signal graph
The button is not functional when there isn't a graph. No need to keep it.
2026-07-30 08:49:56 -07:00
Matthieu Riegler d8a570ec4e refactor(core): update acceptance test
- remove NgModules
- remove non-necessary TestBed.configureTestingModule
- remove non-necessary Eager strategy
- Drop usages of CommonModule
2026-07-30 08:47:53 -07:00
Georgi Serev 1113faf2df refactor(devtools): create Angie component
Introduce a component that provides shared styling for Angie illustrations and predefined sizes for ease of use.
2026-07-30 08:44:59 -07:00
Kam 058c7f9b0c docs: update outdated and broken external links in adev
Several external links pointed at locations that have moved or gone away:

- ng-packagr, webpack, and node-glob renamed their default branch from
  master to main, so the deep links into those repos redirect.
- The npm package pages moved from npmjs.org to www.npmjs.com.
- The Angular Material and CDK docs moved from material.angular.io to
  material.angular.dev.
- The semver reference pointed at the defunct semver.io service; point it
  at the SemVer spec at semver.org instead.
- The MDN animationiteration event link had a typo (animationitration).
- compiler-cli's metadata/schema.ts was removed after v12; pin the link to
  the 12.2.x tag where the file still exists.
- The angularindepth.com article is gone (its domain is parked); link to its
  live home on the Angular In Depth Medium publication.
- Google moved the Lighthouse user-timing docs to developer.chrome.com.

Point the links at their current, working locations.
2026-07-30 08:43:35 -07:00
Angular Robot cc4e6119b4 build: update dependency chalk to v6
See associated pull request for more information.
2026-07-30 08:42:26 -07:00
Angular Robot 84cd4da06c build: update dependency jsdom to v30
See associated pull request for more information.
2026-07-30 08:41:46 -07:00
Kam 4b83d09a94 fix(devtools): invoke selectedNode signal in directive tree keyboard guard
`isEditingDirectiveState` used `!this.selectedNode` (a bare signal
reference, always truthy) instead of `!this.selectedNode()`, so the
guard was dead and ArrowDown with no selection threw a TypeError.
2026-07-30 08:38:28 -07:00
Angular Robot e86e12e56c build: update bazel dependencies
See associated pull request for more information.
2026-07-30 08:24:44 -07:00
Angular Robot 88a9621c30 build: update github/codeql-action action to v4.37.4
See associated pull request for more information.
2026-07-30 08:23:12 -07:00
lazerg ae303c4a05 docs: document overlay stacking change in v21 update guide 2026-07-30 08:22:05 -07:00
Alan Agius 32815d5472 ci: add branch tracking comments to dev-infra GitHub actions
Adds `# main` version comments after SHA references for `angular/dev-infra` GitHub Actions across workflows so that Renovate tracks the main branch and proposes updates when digests change.
2026-07-30 08:16:34 -07:00
Alan Agius 892ea7bec4 release: bump Angular DevTools version to 1.19.0 2026-07-30 09:33:55 +02:00
splincode 1a2bcb2295 fix(devtools): avoid initializing profiler in production mode
Defer the timing hook subscription until the timing API is explicitly enabled. Keep production module loading and development initialization covered by isolated browser test targets.
2026-07-29 16:51:09 -07:00
Alan Agius c6e4d5ad6f release: cut the v22.2.0-next.0 release 2026-07-29 22:49:39 +02:00
Alan Agius 25ddd41125 docs: release notes for the v21.2.19 release 2026-07-29 22:46:12 +02:00
Alan Agius 129b5dbd04 docs: release notes for the v22.1.0 release 2026-07-29 22:40:52 +02:00
Alex Rickabaugh 9386c89a28 docs: release notes for the v20.3.27 release 2026-07-29 12:54:52 -07:00
Kam 0d26130a4c docs: invoke signal inputs in adev examples and tutorials
Several adev example and tutorial files read a signal input as a bare
reference (this.foo) instead of invoking it (this.foo()). Because an
InputSignal is a function object, the bare reference is always truthy
and never yields the underlying value, so the surrounding guard or
binding silently did the wrong thing:

- animations open-close(.1/.3): the `!this.logging` guard in
  onAnimationEvent was always false, so the early return never fired.
- form-validation forbidden-name.directive: the `this.forbiddenName`
  ternary condition was always truthy, so validation ran even when no
  forbidden name was configured.
- first-app steps 12 and 14 housing-location: `housingLocation.photo`
  read `.photo` off the signal function (undefined), leaving the
  listing image src empty.

Invoke the signals so the examples reflect correct signal-input usage.
2026-07-29 09:59:17 -07:00
SkyZeroZx 59f6ef690b refactor(forms): modernize signal forms tests to rely on whenStable
Rely on zoneless test scheduling instead of manually triggering change detection. Keep Signals Forms tests aligned with the async-first testing pattern.
2026-07-29 09:57:37 -07:00
Shuaib Hasan Akib 21eed5f8d4 docs: fix self-referential link in defer block description
Replace broken  link with inline code
formatting. The link was pointing to the page itself, as no dedicated block concept page exists at that URL.
corrects 'everytime' to 'every time'.

Update tools/manual_api_docs/blocks/let.md

Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-07-29 09:45:11 -07:00
Kam e70994bdc3 fix(docs-infra): fix undefined CSS custom properties in shared-docs styles
Two custom properties in the shared-docs styles reference tokens that are
defined nowhere, so the declarations are invalid at computed-value time.

_kbd.scss sets the <kbd> text color with var(---tertiary-contrast); the extra
leading dash points at an undefined property with no fallback, so the color
resolves to the inherited value instead of the intended --tertiary-contrast.

_colors.scss builds --light-pink-to-light-purple-horizontal-gradient from
var(--light-purple), which is not defined anywhere (the sibling token is
--light-violet, defined in the same file), invalidating the gradient. The
gradient is not currently referenced, so this corrects a latent malformed
declaration rather than a visible bug.

Point both at the defined tokens: --tertiary-contrast and --light-violet.
2026-07-29 09:44:35 -07:00
Shuaib Hasan Akib ec87f04200 refactor(common): replaces the deprecated positional subscribe arguments with the
recommended observer object
2026-07-29 09:43:52 -07:00
SkyZeroZx 90ac011fa9 docs: clarify behavior of credentials option during SSR on Node.js 2026-07-29 09:41:28 -07:00
Kam 3d09713386 feat(devtools): show Angie on the remaining empty-state screens
Extend the Angie illustrations to the empty states that were still plain
text: the injector providers "No such providers" result, the injector tree
unsupported-version notice, the two profiler timeline placeholders, and the
router tree unsupported-version notice.

Adds the magnifying-glass and question poses as assets; the orthos-back
and sad poses are already in the tree.
2026-07-29 09:40:42 -07:00
Kam 91822538fe fix(docs-infra): fix malformed --webgl-page-background declaration
In the light theme block of _colors.scss, --webgl-page-background and
--webgl-gray-unfilled were written on a single line without a separating
semicolon, and --webgl-page-background wrapped --page-background in an
invalid nested var(). As a result --webgl-page-background got a garbage
value and --webgl-gray-unfilled was never defined in the light theme.

Split them into two well-formed declarations and drop the nested var(),
matching the structure already used in the dark theme block.
2026-07-29 09:04:09 -07:00
Kam 8cd4c89c29 fix(docs-infra): define missing win95 variables in aria autocomplete examples
The retro-themed aria autocomplete examples style the clear button with
var(--win95-gray), var(--win95-dark-gray), var(--win95-light), and
var(--win95-shadow), but none of the three example stylesheets defines
those custom properties. The variables resolve to nothing, so the button
falls back to inherited theme colors — color: var(--win95-shadow) becomes
the light-theme text color in dark mode, leaving the button unreadable.

Define the four variables in :host of each example, matching the values
already used by the sibling aria tree examples, so the clear button keeps
its Windows 95 look in both light and dark themes.
2026-07-29 09:02:54 -07:00
Kam 48c1e5bb0f fix(docs-infra): replace undefined --gray-50 in retro aria examples
The retro variants of the toolbar, select, and multiselect aria examples
tint the pressed button background with
color-mix(in srgb, var(--retro-button-color) 60%, var(--gray-50)), but
--gray-50 is defined nowhere. Per the CSS spec, a var() with no fallback
pointing at an undefined property invalidates the whole color-mix(), so the
declaration is dropped and the pressed-state tint never applies.

Define a local --retro-pressed-tint token in each example's :host (#fbfbfb,
the value $gray-50 resolved to) with a :host-context(.docs-dark-mode) override
to #151417, and use it for the pressed-state mix. This keeps the example
self-contained rather than depending on adev's global token scope, while
staying theme-aware in both light and dark, following the same token-flipping
pattern used in code-editor.component.scss.
2026-07-29 08:59:54 -07:00
Angular Robot 947859d029 build: update pnpm to v11.17.0
See associated pull request for more information.
2026-07-29 08:55:36 -07:00
Kristiyan Kostadinov 2a141847a5 fix(forms): add utility to assert that value is a field tree
Adds the `isFieldTree` utility that allows users to assert whether a value is a field tree. This is something that has come up on Material recently and will be useful for users as well.

Fixes #69984.
2026-07-29 08:53:24 -07:00
Matthew Beck d44b3224d9 test(compiler-cli): add compliance case for @HostListener on a property
`@HostListener` is not limited to methods — it is equally valid on a property
holding a function, which is the idiomatic way to keep `this` bound:

    @HostListener('window:beforeunload', ['$event'])
    private onUnload = (event: BeforeUnloadEvent) => {...};

Every existing host-listener compliance case declares the handler as a method,
so the property form was uncovered. This adds a case exercising both a public
and a private function-valued property, one of them with a global (`window:`)
event target, and locks in the emitted chained `ɵɵlistener` calls plus
`ɵɵresolveWindow`.

Verified against all four compliance modes (full, partial/linked,
declaration-only); GOLDEN_PARTIAL.js regenerated via the golden update rule.
2026-07-29 08:52:53 -07:00
Matthieu Riegler 36474f7011 refactor(common): remove duplicate helper function
We have `useAutoTick` in our private shared utils.
2026-07-29 08:49:15 -07:00
Maikel van Dort 9373d22a48 docs: remove semicolon text node 2026-07-29 08:48:34 -07:00
Angular Robot 4eb0ed077c build: lock file maintenance
See associated pull request for more information.
2026-07-29 08:46:37 -07:00
Matthieu Riegler c1025a0510 refactor(core): Migrate more tests off fakeAsync
This will prevent to polute the agent context with outdated/bad practices.
2026-07-29 08:46:01 -07:00
Alan Agius 2bcd12a6a5 docs: update default value for strictTemplates
Updates the strictTemplates documentation in Angular compiler options to note that the default is true, replacing the reference to the obsolete ng new --strict flag.
2026-07-29 08:42:11 -07:00
Edu 1b09130640 feat(devtools): rename DevTools tab to "Angular & Wiz" for Googlers
Conditionally update the browser DevTools tab name to "Angular & Wiz" if the user is identified as a Google employee via internal corp network detection.
2026-07-29 08:41:07 -07:00
Jaime Burgos de240a5d0e fix(http): enable xsrf for root-provided HttpClient
Include the XSRF interceptor in the root token factory so the automatically provided HttpClient retains the documented default protection without requiring provideHttpClient().
2026-07-29 08:40:09 -07:00
brysonbw d5e8b1ef7a feat(forms): allow permanent hidden fields in signal forms
Allow the hidden utility function to be called without a configuration object to make fields permanently hidden.
2026-07-29 08:39:39 -07:00
SkyZeroZx f33ee95045 fix(http): match header values exactly when deleting
Normalize value-specific HttpHeaders deletions before filtering. The string overload previously used String#indexOf and removed shorter values contained within the requested deletion value, potentially widening outgoing request metadata.

Preserve delete-all behavior only when no value is supplied, and cover string, array, and empty-string deletion.
2026-07-29 08:39:07 -07:00
SkyZeroZx ff02a16749 fix(http): preserve immutability of materialized clones
Prevent lazy HttpHeaders and HttpParams clones from reusing value arrays owned by a materialized source. Append and value-specific delete operations previously mutated those shared arrays, violating the immutable API contract and allowing request metadata to bleed into later requests.

Share value arrays until an update mutates a specific header or parameter, then copy only that array. Cover the affected append and delete paths with regression tests that materialize the source first.
2026-07-29 08:39:07 -07:00
Georgi Serev 184c4797b8 refactor(devtools): rename timing API to performance track
Rename Timing API to Performance Track to better reflect the purpose of the actual feature;
Migrate the settings data object to match the new name and drop some redundant keys.
2026-07-29 08:38:39 -07:00
Jaime Burgos 840f071566 docs: Adds HTTP communication guidance to Angular Skills 2026-07-29 08:37:14 -07:00
SkyZeroZx f57d5d5c8c fix(core): account for namespaces in host binding sanitization (#69558)
Make runtime URL sanitizer selection namespace-aware so SVG and MathML host bindings match the security schema.

Cover SVG href/xlink:href and MathML href host binding cases, including dynamic hostElement resolution.

PR Close #69558
2026-07-29 08:36:32 -07:00
SkyZeroZx d06e3748b7 fix(core): sanitize host bindings on concrete hosts (#69558)
Host binding sanitization previously used the declaring directive or component selector to choose a compile-time security context. The same host binding can execute on a different concrete element through hostDirectives, inherited host bindings, dynamic directives, or createComponent hostElement usage.

Compute host binding security contexts against possible concrete hosts and defer URL versus ResourceURL selection to runtime when necessary. Resolve dynamic root host TNodes to their native tag before sanitizer and security-sensitive attribute checks.

Fixes angular#69550

PR Close #69558
2026-07-29 08:36:32 -07:00
Suraj Yadav 5ad8231397 fix(migrations): correctly detect then/else keywords in control flow migration
The control flow migration determines whether an `*ngIf` uses a `then`
and/or `else` clause by regex matching the raw microsyntax string for
the literal keywords `then`/`else`. The regexes only checked that the
keyword was preceded by a non-word character, but not that it was
followed by one.

As a result, a template reference name that merely starts with `then`
(e.g. `else thenBlock`) or `else` was misidentified as the `then`/`else`
keyword itself. This caused the migration to take the wrong code path
(e.g. then+else instead of else-only), which in turn made
`getTemplateName()` compute a `slice(start, end)` with `start > end`,
producing an empty template name. That empty placeholder was never
resolved and was silently emitted as an invalid
`<ng-template [ngTemplateOutlet]=""></ng-template>`, dropping the
original template content without any warning.

Add a negative lookahead `(?![\w\d])` to both regexes so `then`/`else`
are only matched as whole keywords, not as a prefix of a longer
template reference name.

Fixes #69914
2026-07-24 13:56:17 -07:00
Matthew Beck 5245ca5ba7 test(compiler-cli): format compliance TEST_CASES.json with prettier
Reformats the TEST_CASES.json files touched by the following change so they
satisfy the repo's prettier check (short inputFiles/files arrays collapsed to a
single line). Pure formatting; the parsed JSON is unchanged. Split into its own
commit so the coverage change that follows is easy to review.
2026-07-24 13:55:33 -07:00
Kristiyan Kostadinov e606a020e9 fix(language-service): account for strictTemplates being enabled by default
We were raising the suggestion about enabling `strictTemplates` when `strictTemplates` is ommitted, however the option is now enabled by default.

Fixes #69905.
2026-07-24 13:45:24 -07:00
Angular Robot 7cbf5e3c2b build: update all github actions
See associated pull request for more information.
2026-07-24 13:43:29 -07:00
Ben Hong 17845308ea docs: modernize directives guides (#69822)
Co-authored-by: Matthieu Riegler <kyro38@gmail.com>

PR Close #69822
2026-07-24 10:36:58 -07:00
Ben Hong 4e7aaa48f5 docs: smooth out directives guide narrative flow (#69822)
PR Close #69822
2026-07-24 10:36:58 -07:00
Kam 28d59e8d63 docs: use https for external links in adev
Several guides, examples, and the update-guide recommendations linked to
external resources over insecure http. Switch them to https.
2026-07-24 08:28:08 -07:00
mfstapert 738b8fe9d2 docs: update attribute testing guide to include canonical example with local component 2026-07-24 08:27:15 -07:00
Jens Kuehlers 25dbe79507 docs: add v23 release and change to yearly release cycle
## Summary

This PR adds v22.x and v23 release dates. It also changes Angular's release cadence to a yearly cycle.

## Why we are making this change

The community has long requested less frequent major releases due to the impact of breaking changes and upgrades for their projects as well as for enterprise customers. Additionally, a longer release cycle provides increased API stability for developers using agentic workflows, while still delivering a reasonable cadence of API upgrades and migrations.
2026-07-24 08:26:32 -07:00
Kristiyan Kostadinov d79b3b65e9 refactor(core): align navigation types with built in ones
Aligns our clone of the navigation API types with the built-in TypeScript types. This is related to an internal issue.
2026-07-24 08:26:02 -07:00
Doug Parker e779309930 release: bump Angular DevTools version to 1.18.0 2026-07-23 12:02:11 -07:00
Pawel Kozlowski 3bf24306be docs: release notes for the v22.1.0-rc.0 release 2026-07-22 16:45:32 +02:00
Pawel Kozlowski c855a5689f release: bump the next branch to v22.2.0-next.0 2026-07-22 16:45:32 +02:00
Pawel Kozlowski 509cad6e15 docs: release notes for the v22.0.8 release 2026-07-22 16:35:02 +02:00
Pawel Kozlowski e428df2b89 build: update pnpm-lock.yaml
Update pnpm lock after it got desychronized in
791b0646c8 build: update all non-major dependencies
2026-07-22 16:18:13 +02:00
Kam ab52df470a fix(docs-infra): fail the guide build when a markdown file starts with a BOM
A leading UTF-8 byte order mark (U+FEFF) before the first `#` stops the
Markdown parser from recognizing the heading, so the guide renders its
title as a paragraph and drops the standard docs header. The character
is invisible, so it cannot be caught in review.

Add a check in the guides generation pipeline that throws when a source
file starts with a BOM, failing the build with the offending file name.
This sits alongside the existing unknown-anchor check and prevents the
regression fixed in #69889 from recurring.
2026-07-22 14:26:19 +02:00
Kam f12db89659 docs: fix first heading rendering as paragraph on two template guides
The ng-container and binding template guide files each began with a
UTF-8 BOM (EF BB BF) before the leading `#`. The docs markdown parser
only promotes `#` to an H1 when it is the first character on the line,
so the BOM demoted the title to paragraph text (`<p># ...</p>`) and the
standard docs header (breadcrumbs, page title, edit button) never
rendered.

Stripping the BOM restores `#` as the first character, so both pages
now generate the proper `<header class="docs-header">` block. Verified
by rebuilding //adev/src/content/guide/templates:templates and
inspecting the generated HTML.

Fixes #69889
2026-07-22 14:26:19 +02:00
Angular Robot 9a1e620603 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-07-22 13:25:54 +02:00
hawkgs e23541b263 fix(zone.js): vitest patching of describe/it curried calls
Separate direct from curried calls of `describe`/`it` modifiers
(direct: `skip`, `only`, etc.; curried: `runIf`, `each`, etc.)
and perform the required patching to them.

Fixes: #69748
2026-07-22 12:34:00 +02:00
Jaime Burgos d14696e430 fix(common): preserve crossorigin on image preloads
Propagate the crossorigin attribute from priority NgOptimizedImage hosts to SSR-generated preload links. Keep preload and image requests in the same credentials mode to avoid an anonymous image issuing an earlier credentialed request.
2026-07-22 12:31:52 +02:00
Kam 6557df5dbe docs: update stale Twitter reference to X in the URL matcher guide
Twitter is now X. In the custom-route-matcher guide, point the author-credit
link at x.com and refer to an "X (formerly Twitter) handle" (clarified once,
then "X handle"), matching the "X (formerly Twitter)" wording already used in
the footer, navigation, and update guide.
2026-07-22 12:01:16 +02:00
Nikita Barsukov cb1841d10b docs: outdated section in the Signal Forms | Custom controls page 2026-07-22 12:00:06 +02:00
SkyZeroZx d955d67b57 docs: clarify usage of 'same-origin' mode and add SSR considerations 2026-07-22 11:58:56 +02:00
SkyZeroZx 6371f0beb1 docs: add skills for Angular pipes 2026-07-22 11:52:33 +02:00
SkyZeroZx 6ac3e26fe0 docs: clarify pipe usage to avoid DI misuse 2026-07-22 11:50:12 +02:00
Suraj Yadav 49672c437b fix(migrations): correctly migrate ngClass with mixed space-separated keys
Preserve NgClass import on partial migration and increment
skippedNgClassCount when an unmigrable mixed binding is encountered.
2026-07-21 19:20:20 +02:00
splincode 8201cebc49 refactor(compiler): enforce exhaustive defer trigger handling
Store the trigger kind before each switch and assign the value to `never` in the fallback branch.

This removes the `any` casts and makes the switches exhaustive. Adding a new `DeferTriggerKind` without handling it in either phase now produces a TypeScript compilation error.

Runtime behavior and error messages remain unchanged.
2026-07-21 19:19:02 +02:00
Angular Robot 9bf8b8ca56 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-07-21 17:20:55 +02:00
Kam 8422da814d feat(docs-infra): react with Angie in the playground minigame
The angle-guessing minigame's result popup personifies your score with a
hand-drawn stick-figure that changes expression by accuracy. Now that Angie
appears across adev — the 404 page, docs search, the embedded editor, the
tutorial intros and completions — give the minigame the same treatment so
its result feels consistent with the rest of the docs.

Replace the result reactor's stick-figure illustration with an Angie pose
keyed to accuracy (seven tiers, superhero down to angry). She is revealed
once the accuracy counter finishes counting up, popping in beside a speech
bubble that carries the round's existing quote. The result popup is widened
so Angie and the bubble sit side by side, and the share link is moved from
twitter.com to x.com.

This removes the previous hand-drawn stick-figure result art. NG the Angle,
the interactive character in the play area, is unchanged.
2026-07-21 17:19:58 +02:00
Angular Robot 791b0646c8 build: update all non-major dependencies
See associated pull request for more information.
2026-07-21 17:17:43 +02:00
Matthieu Riegler 3497c9b943 fix(forms): ensure pending status propagates to the root form in signal forms
Previously, the `pending()` status on a field's `ValidationState` only checked if the field itself or its immediate children had a pending asynchronous validator by directly inspecting `asyncErrors()`. This meant that a pending asynchronous validator deep within a nested form (e.g. on a grand-child) would not correctly bubble the `pending` state up to the root form.

fixes #69840
2026-07-21 13:48:32 +02:00
Angular Robot 22aecf5ed9 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-07-21 13:28:27 +02:00
Angular Robot 9ca95d8f0e build: update bazel dependencies
See associated pull request for more information.
2026-07-21 13:25:46 +02:00
Angular Robot 2bc2146e09 build: update pnpm to v11.15.1
See associated pull request for more information.
2026-07-21 12:08:13 +02:00
Matthew Beck eb3e480360 test(compiler-cli): cover DOM-only vs full instruction set across compilation modes
Adds a compliance case pinning the instruction-set selection for a
directive-free standalone component:

  - full compile: the compiler can prove the template has no directive
    dependencies, so it takes the DOM-only fast path
    (`ɵɵdomElementStart`/`ɵɵdomElementEnd`).
  - local compile: the compiler cannot inspect dependencies, so
    `hasDirectiveDependencies` is forced true and the full instruction
    set is emitted (`ɵɵelementStart`/`ɵɵelementEnd`).

This mode-dependent switch was previously only exercised incidentally by
the `foreign_component` case, which couples it with foreign-component
compilation. The new case isolates it.
2026-07-21 11:06:36 +02:00
Alan Agius 3499a1321b fix(core): ensure SVG animation attributeName is checked case-insensitively
Currently, the SVG sanitizer checks a static set of candidate attribute
names (`attributeName` and `attributename`). This approach misses other case
variations (such as `attributenAme` or others), which could potentially
bypass sanitization when binding sensitive attributes like `href` on
`<set>` or `<animate>` elements.

This change retrieves all attribute names of the SVG element, performs a
case-insensitive comparison with `'attributename'`, and sanitizes the value
if a match is found.
2026-07-21 11:05:02 +02:00
Kam d2c0e1ec77 feat(docs-infra): bookend the tutorials with Angie
The tutorial intro and "next steps" pages were plain headings with no
send-off. Bookend each tutorial with Angie: a greeting pose welcoming
learners on the intro page, and a superhero pose congratulating them on
the completion page, each beside a speech bubble.

The bubble treatment from the 404 page lived inside the not-found
component, so it's extracted into a reusable docs-content style
(docs-tutorial-mascot) usable from tutorial markdown, and applied to the
intro and completion pages of the Learn Angular, Signals, and Signal
Forms tutorials.
2026-07-21 11:03:21 +02:00
Alan Agius 4461e8fdbc build: update devinfra commit and correct module file reference in ts version validation
Update devinfra sha to latest version.
2026-07-21 11:01:03 +02:00
Angular Robot 3c9820f3e0 build: lock file maintenance
See associated pull request for more information.
2026-07-21 10:58:37 +02:00
Suraj Yadav 223e40279f fix(migrations): preserve NgClass import on partial migration
When only some NgClass usages are migrated (partial migration),
the NgClass import should be preserved in the module/component
imports if it is still used elsewhere.
2026-07-20 18:14:35 +02:00
Kam 79fe1c3a05 fix(docs-infra): only claim a search on the 404 page when results exist
The "Page Not Found" page always rendered the sentence "We have
initiated a search for the term extracted from the URL", but the
NotFound component only runs a search when a term can be extracted,
and only renders results when there is at least one hit. On a 404
with no extractable term or no matching results, the page asserted
a search it never backed up.

Gate the sentence behind the same searchResults() check that guards
the results list, so the empty state simply reads "We couldn't find
what you were looking for."
2026-07-20 16:04:29 +02:00
Pawel Kozlowski b8a0fa00c9 build: update pnpm-lock.yaml
This commit updates the pnpm-lock.yaml to reflect differences in node and https-proxy-agent transitive dependencies.
2026-07-20 16:02:38 +02:00
arshiya tabasum 3192dccaa3 fix(http): prevent transfer cache key collisions
`makeCacheKey` joined the request fields with `|` before hashing. The url
and the serialized body can contain `|` themselves, so a shifted field
boundary (url `/items/a` + body `b|c` vs url `/items/a|b` + body `c`)
produced the same joined string and the same key, letting two distinct
requests share a transfer cache slot.

Join with `\0` instead, which cannot occur in a valid url or in encoded
params, so the field boundaries cannot be forged by field content.
2026-07-20 14:39:51 +02:00
Kam 00699f3e66 refactor(devtools): add alt text to the empty-state screen illustrations
The Angie illustrations on the DevTools empty-state screens (added in
#69786) shipped with an empty `alt` and `aria-hidden="true"`. Give them
descriptive alt text and drop `aria-hidden` to improve accessibility.
2026-07-20 14:25:17 +02:00
Angular Robot e27d67f3ec build: update github/codeql-action action to v4.37.1
See associated pull request for more information.
2026-07-20 14:23:57 +02:00
Kam d6cad90b3a docs: fix broken link to Angular AI Skills page
The MCP server setup guide linked to /ai/skills, which 404s. The
page lives at /ai/agent-skills. Update the link to point to the
correct route.

Fixes #69838
2026-07-20 11:50:35 +02:00
Kam b26c1abe07 feat(devtools): show Angie on tab empty states
The Transfer State and signal-graph tabs render bare-text placeholders
when there's nothing to show. Add the Angie mascot to both, matching the
pattern already shipped on the top-level DevTools screens (#69786):

- Transfer State "isn't using Transfer State" card: replace the
  swap_horiz icon with the teaching pose.
- Signal graph "No signals in this component": add the orthos-back pose
  above the message.
2026-07-20 11:50:05 +02:00
Kam f032f5ac1f docs: document the inlineStyleLanguage workspace config option
The `inlineStyleLanguage` build option has existed since v12 but was
never listed in the workspace configuration reference. Add it to the
"Extra build and test options" table alongside the other style options,
documenting its accepted values (css, less, sass, scss) and default.

Fixes #69801
2026-07-20 11:21:44 +02:00
hawkgs a7ebf1cd69 refactor(devtools): reorganize backend code
Organize code into domain/feature-specific folders and a shared API folder.
2026-07-20 11:15:53 +02:00
Angular Robot 79c81b62b9 build: update actions/setup-node action to v7
See associated pull request for more information.
2026-07-20 11:13:50 +02:00
hawkgs 2aecfb0f38 refactor(devtools): format code
Format DevTools TypeScript files.
2026-07-20 10:48:28 +02:00
Georgi Serev 075ed05480 docs(devtools): add a settings doc
Add a doc describing the settings mechanism and the process of updating the settings options.
2026-07-20 10:46:50 +02:00
Pawel Kozlowski 7a626175f7 Revert "fix(forms): preserve intermediate number values in signal forms"
This reverts commit 2e32872720.
2026-07-20 10:45:01 +02:00
Matthew Beck f8c9e9d736 release: cut the v22.1.0-next.6 release 2026-07-15 21:30:09 -07:00
Matthew Beck 265de873d8 docs: release notes for the v22.0.7 release 2026-07-15 21:25:30 -07:00
XananasX7 d43acaf80c ci: harden workflow against expression injection
Interpolating GitHub context values directly into `run:` steps creates
an expression-injection vector. Move the affected values into an `env:`
block and reference them as environment variables in the shell script
instead. This prevents shell metacharacters in context values from
altering step behaviour.

Signed-off-by: El Mehdi Abenhazou <mehdiananas007@gmail.com>
2026-07-15 17:44:44 -07:00
Jaime Burgos 2e32872720 fix(forms): preserve intermediate number values in signal forms
Preserve raw native input text while editing so parsed model values are not written back on every keystroke.
2026-07-15 15:56:48 -07:00
Angular Robot f034c02e67 build: update cross-repo angular dependencies to v22.1.0-next.4
See associated pull request for more information.
2026-07-15 14:49:48 -07:00
splincode 24a3c63976 test(elements): disambiguate the setTimeout spy type
Bind spyOn explicitly to Window so Jasmine uses the DOM setTimeout signature that returns a number instead of the Node.js Timeout type. Remove the unsafe any cast and the obsolete TODO.
2026-07-15 14:48:28 -07:00
Kam d4f2313e4d feat(devtools): show Angie on the empty-state screens
The DevTools state screens (Angular not detected, unsupported version,
production build) showed a plain Material icon above the message. Show
the Angie mascot instead, matching the treatment already used across
angular.dev (the 404 page, empty search, the preview error state).

Each screen uses a pose that fits its message: the dizzy `error` pose for
"application not detected", `coding-01` for the version-upgrade prompt,
and `sad` for the production build notice.
2026-07-15 14:48:01 -07:00
Doug Parker d7a13b989a release: bump Angular DevTools version to 1.17.0 2026-07-15 13:25:23 -07:00
cexbrayat 0ae6d81ed2 fix(core): preserve explicit input transform write type
If a directive has an input declared as `dismissible = input<boolean>(true, {transform: booleanAttribute});` then the following templates were not compiling:

```
<div directiveName dismissible="true"></div>
<div directiveName dismissible></div>
```

This commit fixes the issue, without breaking contravariant consumers.
2026-07-15 12:02:18 -07:00
arshiya tabasum 359fb503b8 fix(common): avoid prototype lookups in date format caches
The NAMED_FORMATS and DATE_FORMATS caches were plain objects read with a
truthy check keyed by a token from the format string, so a token matching
an inherited Object member (e.g. `__proto__`) resolved to a prototype
value. Create both caches with a null prototype so only real entries are
returned.
2026-07-15 12:01:49 -07:00
Shuaib Hasan Akib 37f3279fe7 refactor(forms): warn when a text input receives a null value in Signal Forms
Native text `<input type="text">` controls do not support `null` values.
When a Signal Forms model bound to a text input is set to `null`, the value
is silently coerced to an empty string.
2026-07-15 12:01:13 -07:00
Angular Robot 38d59e8244 build: update pnpm to v11.13.0
See associated pull request for more information.
2026-07-15 12:00:48 -07:00
Georgi Serev 98115e8137 refactor(devtools): revamp highlighter
Revamp the highlighter by introducing a completely new mechanism.
2026-07-15 11:59:04 -07:00
Kristiyan Kostadinov 68ac204074 fix(core): ignore processing instruction syntax in templates
Updates the template parser to detect and ignore processing instruction syntax (e.g. `<? foo ?>` or `<? foo >`). Currently it is being printed out as text.

Fixes #34371.
2026-07-15 11:57:02 -07:00
Paweł Maniecki ea83f13388 docs: update "browser set" links to avoid bad redirect
"Supported browsers" page got moved from
https://web-platform-dx.github.io/web-features/supported-browsers to https://web-platform-dx.github.io/supported-browsers/

There's a redirect in place, but it drops the query parameter with the date, so all versions link to the current browser set.
2026-07-15 11:55:24 -07:00
Kam 6a3487f7b7 feat(docs-infra): greet visitors with Angie in the cookie popup
The cookie consent popup showed only text and two buttons. Add the
Angie greeting pose to it so the first thing a new visitor sees carries
the same mascot treatment already used across the docs (the 404 page,
empty search results, the preview error state).

The message and mascot sit in a flex header row; the two action buttons
now share the row equally so they fill the card instead of leaving a
trailing gap. Layout only, the consent behaviour is unchanged.
2026-07-15 11:54:50 -07:00
Cameron Smick d997a96b47 refactor(core): move signal debug graph interfaces to primitives/devtools
Move the DebugSignalGraph, DebugSignalGraphEdge, and DebugSignalGraphNode interfaces from packages/core/src/render3/util/signal_debug.ts into the packages/core/primitives/devtools/src package. This decouples the signal graph debug types from runtime render3 utilities and allows devtools and internal core tooling to import them directly from primitives as type-only exports.
2026-07-14 11:09:22 -07:00
CYANO-01 fb6b354fbd fix(platform-browser): prevent ReDoS in SOURCEMAP_URL_REGEXP
Replace the lazy quantifier (.+?) with a negated character class
([^\s*]+) that excludes whitespace and asterisks. Source map URLs
never contain these characters, so the fix is semantically
equivalent while eliminating the O(n²) backtracking path triggered
by unclosed /*# sourceMappingURL= fragments.

Fixes: polynomial ReDoS in addBaseHrefToCssSourceMap
2026-07-14 10:57:20 -07:00
Sonu Kapoor 6d043f8657 fix(http): prevent interceptor signal reads from leaking into calling reactive contexts
When `HttpClient` is called from within an `effect()` or other reactive
context, any signal reads performed inside HTTP interceptors were
inadvertently tracked by that context. This caused the effect to
re-execute whenever those signals changed, regardless of whether the
signal was semantically related to the HTTP call.

The fix wraps the interceptor chain invocation in `untracked()` so that
signal reads inside interceptors — both functional (`withInterceptors`)
and class-based (`withInterceptorsFromDi`) — are invisible to the
calling reactive context. This matches the precedent set by the resource
API, which also wraps its loader in `untracked()` for the same reason.

Fixes #58682
2026-07-14 09:21:07 -07:00
LordKay-sudo ae0ec7315c fix(compiler-cli): re-tag SourceFiles after TsCreateProgramDriver.updateFiles()
TypeScript reuses SourceFile objects between old and new programs, so untagging the old program also untags shared files in the new program. Re-apply shim tags on the new program to prevent getSemanticDiagnostics() crashes with TS 5.5+.
2026-07-14 09:18:35 -07:00
Ben Hong ca377900a2 docs: add native html validation clarification in signal forms docs 2026-07-14 08:01:03 -07:00
Angular Robot 2732c5f63c build: lock file maintenance
See associated pull request for more information.
2026-07-14 07:59:16 -07:00
Kam d5e0b131ed feat(docs-infra): show Angie in the error snack bar
The error snack bar (the chunk-load reload prompt and the embedded
editor's memory / mobile alerts) showed only text and an action button.
Add an Angie press-kit pose to the left of the message so the failure
state matches the mascot treatment already used for the preview error
card and the empty search states.

The pose is data-driven: ErrorSnackBarData gains a required `pose` field
so each caller picks the mascot that fits the message tone (`greeting`
for the docs-updated reload prompt and the mobile notice, `error` for
the out-of-memory warning). The message moves into a `<p>` that flexes
to fill the row, keeping the action button aligned to the right.

Presentation only; when and why the snack bar appears is unchanged.
2026-07-13 14:47:26 -07:00
Matthieu Riegler d55f5c4ce5 docs: Add mention that about signal narrowing on @switch blocks 2026-07-13 12:59:36 -07:00
Kam f6a00ffde5 docs(docs-infra): remove orphaned IDX config left behind by #68946
PR #68946 removed the "Open in Firebase Studio" (Project IDX) launcher
from the embedded editor, but left its supporting configuration behind:
a per-tutorial `idx/dev.nix` workspace file in seven tutorials, plus an
`'idx'` entry in `excludeFromRoot` whose only job was to keep those
folders out of the StackBlitz/download bundle.

With the launcher gone nothing reads these files anymore, so remove the
seven `dev.nix` configs and the now-dead `'idx'` exclude entry.
2026-07-13 11:50:57 -07:00
Shuaib Hasan Akib aca7371431 fix(docs-infra): don't show $ prompt on empty lines
Fenced shell code blocks prepended a `$` prompt to every rendered line  via a CSS `::before`, including blank lines are not commands to run.
2026-07-13 11:50:09 -07:00
Kam f94da4d5ca fix(docs-infra): render the Console tab error badge in the embedded editor
The Console tab's error-count badge lives in an `<ng-template
mat-tab-label>`, but the component didn't import `MatTabLabel`, so
Material ignored the templated label and fell back to the plain
"Console" text. Import it so the badge renders when there are errors.
2026-07-13 11:48:54 -07:00
Alan Agius 13d9cc36c0 refactor: remove obsolete @types/babel__core dependency
Remove the obsolete @types/babel__core dependency from packages/compiler-cli and packages/localize. This dependency is no longer needed as Babel v8 ships with its own built-in TypeScript definitions.
2026-07-13 08:13:13 -07:00
Georgi Serev f48d2769db refactor(devtools): add static nodes for html-only block content in the component tree
Add `<html_content>` static nodes to the component tree for control flow blocks that render only HTML content.
2026-07-10 14:27:03 -07:00
Angular Robot 4fad2c0a5d docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-07-10 14:20:46 -07:00
Kam 72cc548d34 feat(docs-infra): add Angie to the embedded editor error state
When the embedded editor fails to boot the preview sandbox, the error
card showed only a text message. Add the press-kit Error pose above the
message so the failure state matches the mascot treatment already used
for the loading steps and the empty search states.

The card is also centered in the preview pane (previously pinned 5% from
the top) so the pose and message read as one block. Behaviour is
unchanged; this is presentation only.
2026-07-10 11:12:15 -07:00
Kam e6378eb330 fix(docs-infra): avoid search dialog empty-state flicker while re-querying
The search dialog picked its empty state ("Start typing" vs "No results
found") with `!resultsResource.hasValue()`, which during a re-query looks
identical to a freshly opened dialog since the resource resets its value and
reports `loading`. This flipped the message and mascot back to "Start typing"
mid-search, causing a question -> magnifying-glass -> question flicker on every
keystroke. Add an `emptyState` signal that holds the previous state while a
search is settling, so the dialog only changes once results resolve.
2026-07-10 10:58:53 -07:00
Doug Parker ce4f7adc95 refactor(core): remove deprecated unregisterTool from ModelContext
In the WebMCP specification, tools are unregistered by aborting the `AbortSignal` provided in `registerTool(tool, {signal})`. The deprecated `unregisterTool` method on `ModelContext` is no longer needed or part of the standard, and is now removed from the TypeScript interface definition.
2026-07-10 10:56:41 -07:00
Doug Parker f908140d71 refactor(core): update WebMCP tool registration to be asynchronous
In the latest WebMCP specification and Chromium preview builds, `document.modelContext.registerTool` was updated to be asynchronous and return a `Promise`: https://groups.google.com/a/chromium.org/g/chrome-ai-dev-preview/c/xQWt0b1sZIE/m/UJznbNCIAwAJ?utm_medium=email&utm_source=footer

This commit update adjusts Angular's experimental WebMCP implementation (`declareExperimentalWebMcpTool` and form registration) to be async as well, returning `Promise<void>`.
2026-07-10 10:56:41 -07:00
Angular Robot a8264df6c5 build: update github/codeql-action action to v4.37.0
See associated pull request for more information.
2026-07-10 10:55:03 -07:00
Angular Robot 8cf7f6ec09 build: update all non-major dependencies
See associated pull request for more information.
2026-07-10 10:54:42 -07:00
Matthew Beck 1fb4678207 Revert "fix(core): allow static attributes for explicit input transforms"
This reverts commit 9b9b0e93c9.

This broke g3. Not sure yet why it didn't break externally. We can
investigate and fix following this revert.
2026-07-09 17:58:22 -07:00
leonsenft b178e83307 ci: fix workflows broken by renamed command
This command was renamed in
https://github.com/angular/dev-infra/commit/ff4046900c623801d13f764a1ee59ce7d2b49599.
2026-07-09 16:04:43 -07:00
Angular Robot 4cf5135743 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-07-09 16:04:43 -07:00
arshiya tabasum 2a4f582731 fix(localize): use Object.hasOwn for placeholder lookup in translate
`translate()` looked up substitutions with `message.substitutions.hasOwnProperty(placeholder)`. A message whose placeholder is named `hasOwnProperty` stores that key on the plain substitutions object, shadowing the method, so the lookup calls the substitution value and throws a TypeError. Use `Object.hasOwn` instead, which resolves through `Object` and is unaffected by the shadowed key, matching the recent `I18nSelectPipe` fix.
2026-07-09 12:29:55 -07:00
Bhuvansh855 12fe700ad8 test(forms): register writeback test control as CVA
Register the custom writeback test control as an NG_VALUE_ACCESSOR
so it is recognized as a valid formField host during debounce
writeback testing.
2026-07-09 12:29:06 -07:00
Bhuvansh855 2e0cb52dbf fix(forms): prevent stale CVA writeback during debounce
Use controlValue() instead of value() when synchronizing
ControlValueAccessor instances.

When debounce is active, value() can still contain the
previous model value while controlValue() reflects the
latest user-entered value. This prevents stale values
from being written back to the CVA before the debounce
is flushed.

Adds a regression test covering the debounce scenario.
2026-07-09 12:29:06 -07:00
cexbrayat 9b9b0e93c9 fix(core): allow static attributes for explicit input transforms
This is a follow-up to #67997, which allowed explicit read generics with input transforms, such as `input<boolean>(false, {transform: booleanAttribute})`.

That fixed the declaration, but static template attributes like `dismissible="true"` and bare `dismissible` were still checked as strings against the read type. Allow the fallback write type to include static attribute strings so these template forms compile.
2026-07-09 12:28:25 -07:00
Michael Small cf6d693985 docs: remove \'s from schematics helloWorld block 2026-07-09 12:23:31 -07:00
hawkgs 5ff14e9915 fix(devtools): bump settings z-index due to overlapping elements
Fixes the bug where the Transfer State table header is overlapping the settings window.
2026-07-09 12:19:39 -07:00
franmc01 454af71609 docs: show ng-add schema files in schematics-for-libraries guide
The ng-add walkthrough references two files it never shows: the
collection points to `ng-add/schema.json` and `index.ts` imports its
`Schema` interface from `ng-add/schema.ts`. Add the missing code blocks,
mirroring the generation-support section, so the example is complete.

Fixes #57005
2026-07-09 12:13:50 -07:00
hawkgs 3685755333 refactor(devtools): stop component inspector on esc press
Stop the component inspector when Escape is pressed similarly to Chrome DevTools.
2026-07-09 12:13:05 -07:00
Kam c92d995260 feat(docs-infra): add Angie to the embedded editor loading steps
While the embedded editor's preview sandbox boots, the pane shows a plain
text label for each step (Booting, Creating project, Installing packages,
Initializing dev server). Add an Angie pose above the label so the wait
tells a small story. Behaviour is unchanged; this is presentation only.

Poses map to the existing LoadingStep values:
  Starting / Booting / Creating project -> greeting
  Installing packages                   -> coding-01
  Initializing dev server               -> superhero

The mascot sits in a fixed-size box (object-fit: contain) so swapping
poses of different aspect ratios never shifts the label or progress bar.
2026-07-09 12:00:46 -07:00
Shuaib Hasan Akib 4fc6d6f765 docs: update ng-content syntax to self-closing tags in content projection and component harnesses guides 2026-07-09 11:57:38 -07:00
Shuaib Hasan Akib 13b6bbd6a0 docs(platform-server): add error reference page for NG05703 and wire up RuntimeError
Add a dedicated error reference page for NG05703 (suspicious URL origin
change during SSR) and update the error to use RuntimeError with a
negative code so the error message automatically includes a link to the
docs page in both dev and production builds.

Update affected tests in url_spec.ts, platform_location_spec.ts, and
integration_spec.ts to match the new NG05703-prefixed error message
format.

Fixes: #69667
2026-07-09 11:56:01 -07:00
hawkgs 53ca8c25cb test(language-service): empty template literal interpolation
Ensure that empty template literal interpolation is handled gracefully.
2026-07-09 09:56:40 -07:00
hawkgs da52137724 fix(compiler): parsing of an empty template literal interpolation
Even if we have an `EmptyExpr`, add that expression to the expressions array when a literal is parsed.
The lack of the expression results in a discrepancy in the sizes of the `elements` and the `expressions`
arrays of a `TemplateLiteral`, that result in an error when we visit that same literal due to the missing
expression.

Fixes #69699
2026-07-09 09:56:40 -07:00
arshiya tabasum 5de0ea5f23 fix(localize): build runtime translations map with a null prototype
loadTranslations stores parsed translations into the shared global
$localize.TRANSLATIONS keyed by message id. Those ids come verbatim from
the translations map (typically parsed from a translation file), so a
translation whose id is __proto__ assigns through the inherited __proto__
setter, reparenting the map rather than storing the entry (and throwing
under --disable-proto=throw). Create the map with Object.create(null) in
loadTranslations and clearTranslations so __proto__ is an ordinary key.
2026-07-09 09:56:10 -07:00
Matthieu Riegler 5cb8c733a3 fix(forms): allow multiple async validators
When a parent form element defines an async validator, its resource's `params` function needs to evaluate `syncValid()`, which causes unvisited child form nodes to be lazily instantiated. If any of these lazily instantiated child nodes also define an async validator, their resource is initialized while the parent's `params` function is still evaluating. This incorrectly triggers Angular core's `NG0992` guard (`Cannot create a resource inside the params of another resource`).
This commit exports `ɵsetInParamsFunction` and `ɵisInParamsFunction` from `@angular/core` and uses them in `FieldMetadataState.runMetadataCreateLifecycle` to explicitly detach the lazy creation of form metadata from the parent's reactive `params` context.

fixes #69620
2026-07-09 09:55:29 -07:00
leonsenft 5bd00add07 fix(compiler): support foreign components inside control flow blocks (#69674)
Prepend generated view scope variables to `view.create` in addition to
`view.update` so that expressions evaluated during creation (such as
foreign component property bindings) can resolve context variables from
parent views when nested inside control flow blocks (`@if`, `@switch`,
`@for`). This is necessary to support binding properties to foreign
components inside control flow blocks.
reflect this broader behavior.)

PR Close #69674
2026-07-09 09:38:24 -07:00
leonsenft 2e442f7876 perf(compiler): do not emit tag name when control flow root is foreign component (#69674)
When a control flow block (`@if`, `@switch`, `@for`) contains a single
root element that is a foreign component, do not treat its name as a tag
name for the template container (`conditionalCreate`, `repeaterCreate`).

PR Close #69674
2026-07-09 09:38:24 -07:00
leonsenft e3ac727dfc docs: release notes for the v20.3.26 release 2026-07-08 15:12:57 -07:00
leonsenft 57616af785 docs: release notes for the v21.2.18 release 2026-07-08 15:05:48 -07:00
leonsenft 248d4e5397 release: cut the v22.1.0-next.5 release 2026-07-08 14:46:50 -07:00
leonsenft 099c5c6dc7 docs: release notes for the v22.0.6 release 2026-07-08 14:38:36 -07:00
Matthieu Riegler 25b7afa515 Revert "fix(forms): allow multiple async validators"
This reverts commit 953cdfd66a.
2026-07-08 13:03:48 -07:00
Kam 3ac2c7b2bc feat(docs-infra): add Angie mascot to the not found page
Replaces the plain "Page Not Found" text with the sad Angie mascot
speaking the message from a speech bubble, for a warmer, more on-brand
not-found page. Copy is unchanged and the "Feeling lucky?" search
results are untouched.

The sad pose is added as an SVG asset (cropped tight to the artwork) under
assets/images/angie/. The mascot is decorative (aria-hidden), and it scales
down to stay beside the bubble on mobile.
2026-07-08 12:45:43 -07:00
franmc01 eac04cfb16 docs: clarify runtime component comparison in elements guide
The popup service example framed the comparison against a vague
'previously you had to define a dynamic component' workflow and pointed
readers at steps no guide describes. Compare against today's
programmatic rendering approach with createComponent instead, which is
what the accompanying example actually uses, and link to the
programmatic rendering guide.

Also remove the note about excluding the component from compilation,
which no longer applies to standalone components.

Fixes #55148
2026-07-08 12:19:55 -07:00
Kam 95fbd0bd48 feat(docs-infra): add Angie mascot to adev empty and error states
Several adev states show only plain text today. This brings the Angie
mascot into them for warmer, more on-brand empty states, with no change
to copy or behavior:

- Search dialog: a magnifying-glass Angie on "Start typing to see
  results", a questioning Angie on "No results found".
- API reference: a questioning Angie on "No API items found." and on the
  package filter's "No results found".
- Deprecated API pages: the back-turned orthos pose in the shared
  deprecation warning.

The mascots are decorative (aria-hidden) and sized per placement; the
poses are added as SVG assets under assets/images/angie/.

Also moves the Shiki highlighter init in the jsdoc-transforms spec into a
beforeAll, fixing a flake where the spec failed under randomized test
order.
2026-07-08 12:18:42 -07:00
Matthieu Riegler c0eaaedef3 refactor(core): cleanup Meta service
The service had a rather old implementation. This is mostly a cleanup.
2026-07-08 11:23:54 -07:00
volkanfilazi 8e8c5524bb removed console log 2026-07-08 11:23:00 -07:00
volkanfilazi b542302a23 fix(forms/signals): make extractValue reactive for compat AbstractControl values 2026-07-08 11:23:00 -07:00
ZorphDark 3cd98ffc1f docs: update e2e-testing guide and skill for official integrations 2026-07-08 11:20:01 -07:00
Bhuvansh855 39ea1c559f docs: fix grammar and punctuation issues in guides 2026-07-08 10:46:32 -07:00
Matthieu Riegler 4e4eb6b707 docs: update optional chaining behavior
+ mention the `$safeNavigationMigration` magic function
2026-07-08 10:46:04 -07:00
Matthieu Riegler d93e922517 docs(forms): add jsdoc for ReadonlyFieldState 2026-07-08 10:45:31 -07:00
aparziale 43996cf748 docs: add global form state signals to signal forms guide
Add a new section for 'Form State Signals' in the signal forms essential guide. This documents global signals such as dirty(), valid(), invalid(), pending(), and touched() at the form level, as requested in issue #69544.

Fixes #69544
2026-07-08 10:42:18 -07:00
SkyZeroZx c1829f6d7c docs(docs-infra): Add build-time validation for API and guide links using route manifest
Adds build-time validation to catch broken, stale, or miscased internal documentation links in both JSDoc and markdown, including `/api/` and `/guide/` URLs and their fragments. Updates the documentation pipeline to share the canonical route manifest, ensuring that all references are checked against the current navigation structure.
2026-07-08 10:24:47 -07:00
Matthieu Riegler 42862f7df4 docs: update formatting 2026-07-08 08:54:18 -07:00
Ambati Mohan Kumar 95b7385cfb docs: fix import of AdminPage in Angular routing documentation. #69670 2026-07-07 16:46:38 -07:00
P4 eb2a8ff63f fix(compiler-cli): apply debugName transform to required signal queries
Transform assumed `.required` functions always take options as the first argument.
This is true for `input` and `model`, but not for `viewChild` and `contentChild`,
which take the same arguments as non-required versions.

Change the code to put options for signal queries in the right position,
causing debugName to be correctly generated for signal queries.
2026-07-07 11:05:22 -07:00
Angular Robot c3e688f102 build: update all non-major dependencies
See associated pull request for more information.
2026-07-07 11:04:31 -07:00
Angular Robot 2f8134bdf5 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-07-07 10:51:06 -07:00
Aleksander Bodurri 56847dc77a fix(devtools): highlight SVG and directive hosts correctly
Before SVG hosts could be skipped because the highlighter checked for HTMLElement. A case like <foreignObject appSvgDemo> would not get a proper overlay. The highlighter now works with Element so SVG hosts can be found and measured.

Before Directive only hosts could be skipped because the inspected-page lookup and directive explorer matched component hosts and component ids only. A case like <a routerLink="/todos">Todos</a> could highlight the parent component instead of the anchor, and the RouterLink only tree node could fail to select, highlight, or request an overlay. Id 0 could also miss the highlighted state because the tree treated it as absent. The lookup now stops at the nearest component or directive host, and tree matching accepts component and directive ids using null as the absent state.

Selected overlays could fail to reappear for the same element because unhighlighting removed the overlay but left the selected element cached. selected-element cache is now reused only while its overlay is still connected, and unhighlighting clears the cached element.

Overlay geometry used integer coercion. An SVG or transformed element with a 0.5px bounding box could get a 0px overlay. Overlay positioning now preserves fractional DOMRect values.
2026-07-07 10:18:37 -07:00
Cameron Smick bf6dba878e refactor(core): move devtools ai tool definition types to primitives
Extract the AI tool definition interfaces from the core debug module to the devtools primitives module. This relocates ToolDefinition, ToolGroup, and DevtoolsToolDiscoveryEvent to the primitives folder, exposing them cleanly via "export type" in the devtools entry point, improving module organization and readability.
2026-07-07 10:18:05 -07:00
Kam 6edabc64e5 refactor(vscode-extension): remove duplicated getTokenAtPosition in completions handler
The completions handler kept a local copy of getTokenAtPosition plus three stale TODO comments noting the duplication, but the function is already exported from server/src/utils.ts (hover.ts and others import it from there). Drop the local copy, import the canonical one, and remove the now-meaningless comments.
2026-07-07 10:11:02 -07:00
rootvector2 e5c37f21de fix(router): use safe hasOwnProperty when parsing query params
`parseQueryParam` and the AngularJS-compat `parseKeyValue` accumulate query params into a plain object and check key presence with `obj.hasOwnProperty`, so a `hasOwnProperty` query key clobbers the method and the next lookup throws `TypeError`. Switch both to `Object.hasOwn`, which can't be shadowed by a query key.
2026-07-07 10:09:34 -07:00
cexbrayat fbb705e6fd fix(migrations): remove stale model import in model-output migration
Remove the model import after migrating all model() usages in a file.
2026-07-07 10:08:43 -07:00
arturovt ab618bdc0f refactor(compiler-cli): use BindingType enum check in suffix-not-supported extended diagnostic
Replaces the `node.keySpan.toString().startsWith('attr.')` string allocation in the `suffixNotSupported` extended template check with an O(1) `node.type === BindingType.Attribute` enum comparison.

The diagnostic message string is also extracted to a module-level constant so it is created once at module load time instead of on every diagnostic emit.

Additionally, this change adds missing test coverage for the `.%` and `.em` suffixes, as well as for a plain `attr.` binding without a style suffix.

Measured with a 100-iteration microbenchmark before and after the change (MacBook Pro 2018, Intel CPU):

```ts
const start = performance.now();
for (let i = 0; i < 100; i++) {
  new ExtendedTemplateCheckerImpl(templateTypeChecker, program.getTypeChecker(),
    [suffixNotSupportedFactory], {}).getDiagnosticsForComponent(component);
}
console.log((performance.now() - start) / 100, 'ms/iter');
```

Before: `~0.24 ms/iter`
After: `~0.14 ms/iter` (~40% faster)
2026-07-07 10:05:05 -07:00
Ben Hong b340e44a86 docs: add signal forms testing guide 2026-07-07 10:03:17 -07:00
cexbrayat eac363e92e fix(compiler-cli): detect uninvoked signals in bound expressions using ternary
Extend the interpolated signal extended diagnostic to inspect ternary-bound expressions and report uninvoked signal reads in bound bindings.

```
<div [style.width]="width() ? 1 : width"></div>
```

where the false branch should invoke the signal as `width()`.
2026-07-07 10:01:49 -07:00
SkyZeroZx 0a5a2b768c fix(migrations): preserve transitive NgModule references when pruning
avoids unintended removal of indirectly required modules

Fixes #62865
2026-07-07 10:01:10 -07:00
Kam 5ec0b1668b fix(docs-infra): disable nav-list tooltip on mobile
On mobile, focusing a long nav item shows a matTooltip that escapes the
drawer, ignores inner scroll, and blocks scrolling while open. Suppress
it on mobile using the existing isMobile helper.
2026-07-07 09:54:47 -07:00
Kam 4b0c066e22 fix(docs-infra): keep mobile nav open when closing the search dialog
Backdrop clicks on the search dialog were also closing the open mobile nav drawers. Adds an id to `<dialog>` and references it from both navs' `docsClickOutsideIgnore` arrays.
2026-07-07 09:54:14 -07:00
Ben Hong 7dd35913b6 docs: add composability section to custom controls signal forms 2026-07-07 09:52:17 -07:00
arturovt 73ab88e65b refactor(forms): avoid unnecessary Set allocation in maybeRemoveStaleArrayFields
Three small, behavior-neutral cleanups to maybeRemoveStaleArrayFields:

1. Avoid allocating an empty Set when prevData.byTrackingKey is
   undefined. new Set(undefined) previously created an unused empty
   Set on every call for parents with no tracking keys.

2. Guard the per-element tracking-key check on `oldTracking` being
   defined, skipping the isObject/hasOwn check entirely when there's
   nothing to track.

3. Replace childValue.hasOwnProperty(identitySymbol) with
   Object.hasOwn(childValue, identitySymbol). hasOwnProperty throws
   on null-prototype array elements (Object.create(null)), which
   would crash computeChildrenMap. Object.hasOwn is null-prototype-safe
   and preserves "own property" semantics (does not match inherited
   identitySymbol values).

4. Replace `data.byTrackingKey?.delete(id)` with
   `data.byTrackingKey!.delete(id)`. The optional chaining was dead:
   if oldTracking.size > 0, prevData.byTrackingKey (and therefore
   data.byTrackingKey, same Map reference via the spread) is always
   defined. The `?.` masked this invariant; `!` documents it and
   would surface a runtime error instead of a silent no-op if the
   invariant is ever violated.

Verified via performance.mark/measure instrumented directly inside
the function (count=1 call for a single-field edit in both cases).
Total duration dropped from ~0.7ms to ~0.1ms, consistent with the
avoided Set allocation in (1) and (2).
2026-07-07 09:51:44 -07:00
Angular Robot 3da6d058d3 build: lock file maintenance
See associated pull request for more information.
2026-07-07 09:48:35 -07:00
Shuaib Hasan Akib 01bb0a2f28 refactor(core): remove unused utility functions
Remove `isIterable` from `util/iterable.ts` and
`newTrustedFunctionForDev` from `util/security/trusted_types.ts`
as they are no longer referenced anywhere in the codebase.
2026-07-07 09:48:06 -07:00
Angular Robot 8f7dc479de build: update dependency @mcp-b/webmcp-types to v4
See associated pull request for more information.
2026-07-07 09:46:23 -07:00
moraisacr e91046ffdb docs(ai-tutor): add troubleshooting for MCP setup issues 2026-07-07 09:36:56 -07:00
Ben Hong d837d6270a docs: add signal forms dynamic forms with json guide
Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-07-07 09:27:15 -07:00
Hien Pham 1f6b1cee22 docs: enhance readability of utility methods section in testing guide 2026-07-07 09:20:23 -07:00
Hien Pham cfe847eea8 docs: improve readability of inject, initTestEnvironment, and resetTestEnvironment descriptions 2026-07-07 09:20:23 -07:00
Jan Pilzer f3e2b6bf6a docs(docs-infra): Social & Theme menu placement
Bottom align menus with trigger buttons
Align height of social link icons
2026-07-07 09:19:43 -07:00
marktechson c587555fdd docs: updates press kit
Adds a link to Angular's official mascot, Angie! Community members can now have access to Angie for use that falls within the community guidelines.
2026-07-07 09:18:54 -07:00
Shuaib Hasan Akib 81dd9d6091 docs: fix code snippet formatting and highlight lines
Correct a mismatched line highlight in the documentation examples
and convert tags to the preferred self-closing format for consistency.
2026-07-07 09:15:39 -07:00
SkyZeroZx 901eb4607a docs: clarify HttpClient default provider 2026-07-07 09:14:40 -07:00
Shuaib Hasan Akib cf70bcfef8 docs: update component and directive decorator examples to use concise syntax 2026-07-07 09:14:13 -07:00
Aleksander Bodurri 910557d062 docs(devtools): document how the extension connects to a tab
Add an architecture doc tracing how the Angular DevTools panel, background worker, content scripts, and backend connect per tab and relay messages, with diagrams for the topology and boot sequence.
2026-07-07 09:12:32 -07:00
Sebastian Barfurth 19a66dcc15 docs: point out interoperability of custom Signal Form controls
Any custom Signal Form control
[will actually work](https://github.com/angular/angular/issues/69074#issuecomment-4601225278)
in both Reactive and Template-Driven form contexts. However, this is not obvious
from reading the docs. This PR points this out very explicitly in both the
migration and custom control guide for Signal Forms.

One notable advantage of this interoperability behavior is the ability to
migrate existing `ControlValueAccessor` controls without breaking users. I've
pointed this out separately.
2026-07-07 09:11:41 -07:00
leonsenft a19c02706f refactor(compiler-cli): support foreign imports with isolated declarations
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`.
2026-07-07 09:10:21 -07:00
arturovt 806a3ada26 docs: add NG05200 error reference page for SANITIZATION_UNSAFE_SCRIPT
Adds a reference page for `NG05200`, thrown by `DomSanitizer` when a value is bound to a `<script>` element without being marked trusted via `bypassSecurityTrustScript`. Covers why Angular rejects script content outright, how to reproduce the error, the escape hatch, and the XSS caveat.
2026-07-07 09:09:49 -07:00
Angular Robot 731d665a86 build: update babel monorepo to v8
See associated pull request for more information.
2026-07-06 14:05:15 -07:00
Matthieu Riegler 953cdfd66a fix(forms): allow multiple async validators
When a parent form element defines an async validator, its resource's `params`
function needs to evaluate `syncValid()`, which causes unvisited child form
nodes to be lazily instantiated. If any of these lazily instantiated child
nodes also define an async validator, their resource is initialized while the
parent's `params` function is still evaluating. This incorrectly triggers
Angular core's `NG0992` guard (`Cannot create a resource inside the params
of another resource`).
This commit exports `ɵsetInParamsFunction` and `ɵisInParamsFunction` from
`@angular/core` and uses them in `FieldMetadataState.runMetadataCreateLifecycle`
to explicitly detach the lazy creation of form metadata from the parent's reactive
`params` context.
2026-07-06 14:05:15 -07:00
Kam cd8351a3af docs: fix layout shift when refreshing the stagger example
Clicking "Refresh" toggles the list out of and back into the DOM, but the
`<ul>` lived inside the `@if`, so removing it collapsed the layout and
caused a vertical jump. Wrap the list in a fixed-height `.items-container`
to reserve the space while it re-mounts. Also key the stagger delay off
`$index` so the first item animates immediately instead of being delayed a
step.
2026-07-06 14:04:46 -07:00
Kam 42fc9a4599 docs: use descriptive link text for the AI overview page link
The link on the "develop with AI" page wrapped the verb phrase "to check
out the overview page" in the link text, burying the destination in a
call-to-action. Per the adev writing guide's descriptive-link-text rule,
link only the noun that names the destination.

Change the link text to "overview page" so it clearly indicates where the
link goes.
2026-07-06 14:04:10 -07:00
Alan Agius e3630c23c5 feat(http): add options to allow caching of credentialed and non-cacheable HTTP requests
Adds `includeRequestsWithCredentials` and `includeNonCacheableRequests` options to `HttpTransferCacheOptions`.
2026-07-06 14:03:32 -07:00
Angular Robot 8e090cbe82 build: update bazel dependencies
See associated pull request for more information.
2026-07-06 14:03:09 -07:00
Matthieu Riegler 997b772f28 fix(compiler): use regular optional chaining expression for safe function calls in TCBs
Optional return types should not report non-nullable optional chaning on function calls.

fixes #69609
2026-07-06 14:02:40 -07:00
SkyZeroZx d9639201b3 test(router): Update tests to use currentNavigation()
Updates router integration tests to use the `currentNavigation()` method instead of deprecated `getCurrentNavigation`.

Also replaces direct `setTimeout` calls with the `timeout()` utility function.
2026-07-06 14:01:11 -07:00
Shuaib Hasan Akib 0285f558f9 refactor(forms): improve type safety of RadioControlRegistry._accessors
Replace `any[]` with `[NgControl, RadioControlValueAccessor][]` for the
private `_accessors` field in `RadioControlRegistry`. This aligns the
field type with how it is used in `add()`, `remove()`, `select()`, and
`_isSameGroup()`, which already typed its parameter as
`[NgControl, RadioControlValueAccessor]`.
2026-07-06 13:59:16 -07:00
Angular Robot d60b59a7e9 build: update all github actions
See associated pull request for more information.
2026-07-06 13:54:52 -07:00
Angular Robot d518d8db35 build: update pnpm to v11.10.0
See associated pull request for more information.
2026-07-06 13:52:39 -07:00
Angular Robot fd305c3743 build: update dependency @mcp-b/webmcp-polyfill to v4
See associated pull request for more information.
2026-07-06 13:50:12 -07:00
Cheng-Hsuan Tsai d6e4529b55 docs: update API reference links in aria guides 2026-07-06 13:49:48 -07:00
Kam 551cb3b8b5 fix(docs-infra): lock background scroll while the search dialog is open
The search dialog (Cmd/Ctrl+K) opens as a native modal via `showModal()`, but the
page behind it stayed scrollable, so scrolling drifted the underlying content
beneath the blurred backdrop.

`body` already reserves a stable scrollbar gutter, so setting `overflow: hidden`
while the dialog is open blocks background scrolling with no layout shift. The rule
keys off the dialog's `[open]` state, so it restores automatically on every close
path (Escape, click-outside, navigation) with no script involved.
2026-07-06 13:48:53 -07:00
Kam 95a953145e fix(docs-infra): restyle prefer/avoid code block headers
The "Prefer" / "Avoid" code block headers rendered the style label as
plain inline text joined to the title with a bare "-" separator, giving
the two block types little visual distinction. The taller label also left
the prefer/avoid header at a different height from the plain filename
header, so the copy button's single "top" value could not center it in
both.

Style the label as a small uppercased pill tinted with the block's style
color, drop the "-" separator, add a subtle inset accent under the header,
and swap the heavier "dangerous" icon on "Avoid" for "close". Give every
header a fixed height with box-sizing: border-box and vertically center
its contents so all variants render at the same height and the copy button
stays centered.

This supersedes #69638, folding in its centering fix for the copy button
offset that #69030 introduced.
2026-07-06 13:48:14 -07:00
Shuaib Hasan Akib 9153515422 docs: fix broken ordered list in NG0912 error page
Fenced code blocks between list items in NG0912.md were not indented,
causing Marked.js to treat them as top-level block elements that
interrupt the list. This resulted in two separate <ol> elements being
rendered instead of one.

Indent the code blocks by 4 spaces so they are treated as continuation
content of their list items, and change the second `1.` to `2.` for
correctness.
2026-07-06 13:47:24 -07:00
Kam 12a4e60a4a fix(docs-infra): prevent tab labels from being clipped
The active docs tab applied a 2px bottom border that inactive tabs lacked,
which shrank the active label's content box and clipped its descenders. It
also set `line-height: 1.5` only on the active label, so switching tabs
nudged the text. Reserve the border as transparent on every tab and recolor
it on the active one, and share the label `line-height`, so the letters are
no longer cut and the label stays put when switching.
2026-07-06 13:46:40 -07:00
SkyZeroZx 205acb3494 docs: add docs for deep link support for Angular components in Chrome DevTools profiling 2026-07-06 13:45:40 -07:00
aparziale 207abf1140 fix(docs-infra): strip newlines from class signature in API gen
Prevents multiline generics or implements clauses from breaking the
rendered class signature in the API reference docs.
2026-07-06 13:44:17 -07:00
Hazem Alyaari c894b00d25 docs: fix typos and broken examples in guide content
Correct grammar, punctuation, and code examples across signals, forms, http, and templates guides so copy-paste snippets compile and read clearly.
2026-07-06 13:43:47 -07:00
Bhuvansh855 91fd0ca8db docs: improve Signal Forms complete example 2026-07-06 13:41:20 -07:00
Hazem Alyaari 8c8f3ac528 docs: fix terminology typos in Signals overviews
Fixes #69595

Fixes #69597
2026-07-06 13:40:18 -07:00
Shuaib Hasan Akib 892a6eb69a fix(docs-infra): add target="_blank" to external links in @see JSDoc tags
External links rendered via `@see {@link ...}` and `@see [label](url)`
were not opening in a new tab. The `getHtmlAdditionalLinks` function
now sets `target: '_blank'` on `LinkEntryRenderable` objects whose URL
is external, and `docs-pill-row.tsx` passes the `target` attribute to
the rendered anchor tag.

Fixes: #69593
2026-07-06 13:39:48 -07:00
Kam e4ffb24ecb fix(docs-infra): keep copy link icon out of the search index
The copy link button rendered its icon as a Material Symbols ligature text node, and since the button is appended inside each heading's `.docs-anchor`, that text leaked into the heading and the Algolia crawler indexed values like `Descriptionlink`. The glyph is now rendered via a `::before` pseudo-element using the icon codepoint, so no `link`/`check` text exists in the DOM and headings index correctly again.
2026-07-06 13:39:11 -07:00
Matthieu Riegler 5ad937be5e docs: correct docs about the chain behavior.
Even if the chained resource has a value, it might throw an error.

fixes #69330
2026-07-06 13:37:23 -07:00
Matthew Beck d579ecaf73 feat(compiler): Disable '--global-' error outside of g3 (#68846)
... for now. Should be enabled in the next major.

PR Close #68846
2026-07-06 13:36:24 -07:00
Matthew Beck 8c8b2f7783 feat(compiler): Support css var namespacing in properties (#68846)
Adds support for namespacing css variables in style properties. Behaves
as you'd expect following the implementation for stylesheets generally.

This change also moves the error message into a util function since we
now need to produce the same error in three places.

PR Close #68846
2026-07-06 13:36:24 -07:00
Matthew Beck af5e4e1131 feat(compiler): Add an error for --global-foo cases (#68846)
Using `--global-foo` is now prohibited. We suspect these cases will
likely be typos of `--global--foo` in the future, so we blanket ban them
and direct users to the expected syntax.

PR Close #68846
2026-07-06 13:36:24 -07:00
Matthew Beck f98547675c feat(compiler): Namespace CSS variables to the app (#68846)
Adds logic to inject symbols into CSS variables for runtime namespacing.
The runtime now replaces instances of `%NS%` with a namespacing
variable, limiting reach of CSS variables to the current app. An opt-out
syntax of a `--global` prefix allows users to avoid this behavior.

PR Close #68846
2026-07-06 13:36:24 -07:00
SkyZeroZx bbbcf8fc7f docs: add @see references to Signal Forms 2026-07-06 13:35:20 -07:00
arshsmith1 cbbb1d8ba1 fix(router): handle outlet named __proto__ in segment group maps
Outlet maps are keyed by names read verbatim from the url, so a name like
`__proto__` (e.g. `/one(__proto__:two)`) is assigned through the inherited
`__proto__` setter instead of creating an outlet. This drops the outlet and
mutates the map's prototype, and throws under Node's `--disable-proto=throw`.

Build these outlet maps with `Object.create(null)` so `__proto__` is treated as
an ordinary key. Covers `parseParens` and `squashSegmentGroup` in url_tree.ts,
`createSegmentGroup` in apply_redirects.ts, and `replaceSegment` and
`updateSegmentGroupChildren` in create_url_tree.ts.
2026-07-06 13:34:04 -07:00
SkyZeroZx 95f56d33fe feat(devtools): Adds deep linking from Chrome Performance panel
Enables direct navigation to Angular components from the Chrome Performance panel's flame graph.

This feature integrates Angular DevTools with Chrome's `setOpenResourceHandler` by registering a custom URL scheme (`angular-devtools://component/{instanceId}`).

Closes #63960
2026-07-06 13:32:32 -07:00
SkyZeroZx eab4847a8b feat(core): Adds deep linking from Performance panel to DevTools
Introduces unique, IDs for component instances during profiling.

Embeds these instance IDs into custom `angular-devtools://component/ID` URLs for component and lifecycle hook events recorded in Chrome's Performance panel. This allows users, when deep linking is enabled, to click on a component event in the timeline summary and navigate directly to that specific component instance in the Angular DevTools extension.

Closes angular#63960
2026-07-06 13:32:32 -07:00
Alex Rickabaugh b126dc9726 release: cut the v22.1.0-next.4 release 2026-07-01 14:10:31 -07:00
Alex Rickabaugh c4fa24abf6 docs: release notes for the v22.0.5 release 2026-07-01 13:54:42 -07:00
Bhuvansh855 c4cb66e602 docs: improve introductory resource example 2026-06-30 18:00:03 -07:00
Shuaib Hasan Akib a74801c59c fix(router): fix malformed jsdoc comment for RouterLinkWithHref export
The export statement was incorrectly placed inside the JSDoc comment block,
and there was a stray text fragment "nstead." from the deprecation message.
This moves the export statement outside the comment and removes the stray text.
2026-06-30 17:59:36 -07:00
Kam b9125db156 docs(docs-infra): show the schema function in the validation example
The "schema function" example on the Validation guide page pointed its
visibleLines and highlight ranges at the wrong source lines. The
collapsed view showed the component's imports and model signal instead
of the schema function, and the highlight marked unrelated lines, so
readers had to expand the example to find the code the section is about.

The example file was edited at some point and these line numbers were
not updated to follow it. Point visibleLines at the form() schema call
(lines 29-34) and highlight the three validator calls (lines 30, 31, 33)
so the relevant code is visible by default.

Fixes #69547
2026-06-30 17:57:55 -07:00
Kam a9e3336aae fix(docs-infra): improve code selection contrast in dark mode
The ::selection background mixes only 10% of the accent color into
--octonary-contrast. In dark mode --octonary-contrast resolves to
gray-900 (#151417), which is the same color code blocks use as their
background, so selected code renders ~90% code-background and is almost
invisible.

Add a .docs-dark-mode ::selection override that raises the tint to 30%
so highlighted text stays legible over the near-black surface. Light
mode is unchanged, as its selection already contrasts the white page.

Fixes #69507
2026-06-30 17:56:35 -07:00
Eduard Fischer-Szava 19a912a6ef docs: fix incorrect @defer trigger names and a duplicate word in guides
The @defer guide reused the viewport section's prose in the
interaction and hover sections without updating it:

- interaction: the template reference variable is passed on the
  interaction trigger, not the viewport trigger.
- hover: the element is hovered over and the variable is passed on the
  hover trigger, not "watched to enter the viewport" / viewport.

Also removes a duplicate "keep the" in the routing
customizing-route-behavior guide.

Documentation-only; no code changes.
2026-06-30 17:52:16 -07:00
Hien Pham d748e8160d docs: clear mock after each test and refine expectation for tax calculator call
- We need to clear the mock between different assertions
- We have either toHaveBeenCalledOnce or toHaveBeenCalledExactlyOnceWith matcher
2026-06-30 17:51:36 -07:00
SkyZeroZx b6dbdcfe34 docs: remove ChangeDetectionStrategy.OnPush from Signal Forms tutorial 2026-06-30 17:49:31 -07:00
Michael Small 42affba3b7 docs: remove standalone: true and explicit OnPush from forms skill
docs: remove `standalone: true` from `signal-forms.md`

docs: remove explicit `OnPush` from signal forms skill

docs: remove import of CD strategy
2026-06-30 17:48:51 -07:00
arturovt 311aff05aa fix(common): use Object.hasOwn in I18nSelectPipe to handle null-prototype and shadowed mappings
`I18nSelectPipe.transform()` called `mapping.hasOwnProperty()` directly,
which fails in two edge cases:

- Mappings created with `Object.create(null)` have no prototype and
  therefore no `hasOwnProperty` method, causing a TypeError at runtime.
- Mappings where a key literally named `hasOwnProperty` shadows the
  built-in method return incorrect results silently.

Replace both call sites with `Object.hasOwn(mapping, key)`, which
delegates through `Object` directly and is immune to both issues.

Add two regression tests that demonstrate the broken behaviour before
the fix and pass after it.
2026-06-30 17:46:35 -07:00
Alan Agius 785d254433 ci: setup Node.js in adev-preview-deploy workflow using .nvmrc
Ensures that the correct Node.js version is used.
2026-06-30 17:45:19 -07:00
Kristiyan Kostadinov e844ad18a0 refactor(compiler): move block name normalization into lexer
Previously I intentionally kept the lexer as generic as possible so that block detection can happen later. However, since #62644 we detect blocks in the lexer so we might as well normalize them there so all the upstream code doesn't have to account for things like whitespace.
2026-06-30 17:44:25 -07:00
Kristiyan Kostadinov 292199aa4d fix(compiler): permissive whitespace parsing in default never blocks
Makes the parser more permissive towards whitespaces between words in the `default never` block.
2026-06-30 17:44:25 -07:00
Alan Agius 7a7a612e48 docs: remove fixed font-size from table headers in docs
Removes the fixed font size from table headers to ensure they scale properly and do not appear smaller than the table content.
2026-06-30 17:41:27 -07:00
Alan Agius c92d38c097 docs: update service documentation to compare @Service and @Injectable decorators with a feature comparison table
Closes: #69563
2026-06-30 17:40:51 -07:00
yamanerkam cbd97072f4 fix(docs-infra): don't auto-link code symbols used as link text
When an inline code symbol is used as the text of an explicit markdown
link (e.g. [`httpResource`](/guide/http/http-resource)), the codespan
renderer recognized it as an API symbol and wrapped it in a second
anchor pointing at the API reference. This produced nested <a> tags, so
the explicit link was effectively replaced by the API symbol link.

Disable auto-linking while rendering a link's inner tokens so the
explicit href is preserved, matching the pattern already used by the
heading and docs-card renderers.

Fixes #69549
2026-06-30 17:39:34 -07:00
Angular Robot 2df56d7de0 build: update dependency conventional-changelog to v8
See associated pull request for more information.
2026-06-30 17:35:57 -07:00
SkyZeroZx d7f70616a0 fix(core): reject dynamic script host elements
The previous fix for GHSA-692r-grfm-v8x7 was incomplete because it rejected script tags only when locating an explicit host element. Dynamic component instantiation can also infer the host element from the component selector.

Move the script-host rejection to the point where ComponentFactory has resolved the host element for either path, so createComponent rejects script hosts consistently.
2026-06-30 17:29:36 -07:00
Angular Robot a68e610641 build: update pnpm to v11.9.0
See associated pull request for more information.
2026-06-30 17:28:36 -07:00
Andrew Scott a7bde662c3 refactor(core): allow AnimationClassBindingFn to return undefined or null
The AnimationClassBindingFn type was too restrictive, only allowing `string | string[]`. However, the runtime (`getClassListFromValue`) safely handles `undefined` and `null` values by treating them as no animation.

This change updates the type to allow `undefined` and `null`, which is consistent with other class/style bindings in Angular and avoids requiring workarounds (like empty strings) in host bindings.

Added a compliance test case to verify that `[animate.enter]` with a potentially `undefined` value compiles correctly.
2026-06-30 17:27:59 -07:00
marktechson d791a7f496 docs: updated roadmap 2026-06-30 17:24:02 -07:00
yamanerkam 00226e7d80 fix(docs-infra): align and highlight external-link icon in nav sidebar
The open_in_new icon on external navigation items stayed grey on hover
and sat inset from the chevron column, so it never matched the chevron
items visually.

- Add a hover rule so the icon brightens to --primary-contrast along
  with the label, matching the chevron/text behaviour.
- Override the 1rem max-width reserve inherited from
  .docs-faceted-list-item-text by chaining both classes the span carries
  (.docs-external-link.docs-faceted-list-item-text), so the icon lines up
  with the chevrons at the link's end-padding. Using :host was avoided
  because it breaks the nested `a:hover &` selector.
2026-06-30 17:23:26 -07:00
Shuaib Hasan Akib 3f9d0ee985 fix(docs-infra): support header values containing apostrophes
Update the `headerRule` regex to capture the complete quoted header value. The previous pattern excluded quote characters from the content and failed to parse headers such as:

```angular-ts {avoid, header: "Can't inject interface"}
```

The new pattern matches everything between the opening and closing quote delimiters.
2026-06-30 17:22:35 -07:00
Alex Rickabaugh a5f1b20373 Revert "fix(compiler-cli): include toSignal in debugName transform"
This reverts commit 165995285c. Reason: breaking
in g3 (ngDevMode not defined)
2026-06-30 13:24:17 -07:00
leonsenft a720094deb refactor(core): format @content blocks consistently (#69502)
`@content(name)` -> `@content (name)` to align with other block syntax.

PR Close #69502
2026-06-29 17:34:27 -07:00
leonsenft 555fc20af0 refactor(core): add context support for foreign components (#69502)
Enable foreign components to receive and propagate contextual data
across framework boundaries.

Previously, foreign render functions only accepted component properties,
and foreign content projection instructions (`ɵɵforeignContent` /
`ɵɵforeignContentFn`) did not provide any mechanism to expose foreign
framework context to projected Angular embedded views.

With this change:

- Update `ForeignRenderFn` and `ForeignComponent` interfaces to accept
  an optional context parameter and an optional `GET_CONTEXT` symbol
  method.

- Introduce `FOREIGN_CONTEXT` injection token and
  `provideForeignRootContext` helper to configure root context in
  Angular's DI hierarchy.

- Update `ɵɵforeignComponent` instruction to resolve `FOREIGN_CONTEXT`
  from the injection tree and pass it to the foreign component's render
  function.

- Update `ɵɵforeignContent` and `ɵɵforeignContentFn` instructions to
  wrap embedded view creation with a `ForeignContextInjector` when
  `GET_CONTEXT` is present.

Furthermore, foreign render functions are no longer run inside an
Angular injection context, since it's expected they use the foreign
context support directly.

PR Close #69502
2026-06-29 17:34:27 -07:00
Matthieu Riegler 74803c75cd refactor(compiler): remove visitAttributeComment
In #69463 we forgot to rename the visitor method after renaming the node class
2026-06-29 16:00:03 -07:00
aparziale e653a7bf30 docs(forms): correct signal field access in form model example
The `myForm` field is a callable `FieldTree`, so its value must be read
via `this.myForm().value()`. Fixes two examples that incorrectly used
`this.myForm.value()`.
2026-06-29 14:49:38 -07:00
Paweł Maniecki 165995285c fix(compiler-cli): include toSignal in debugName transform
the toSignal function received a debugName option in 0812ac3bec,
but was not covered by the signalMetadataTransform which sets the debugName in dev mode
automatically.
2026-06-29 14:32:17 -07:00
SkyZeroZx 7ea2a002f5 docs: add documentation for HttpClient response body size limit and related error NG02825 2026-06-29 14:27:26 -07:00
cynavi 433993efa8 docs(docs-infra): fix typo and malformed markdown bullet in angular-developer skill 2026-06-29 14:24:21 -07:00
leonsenft 4847c0e07b refactor(core): enable foreign components to render content lazily
Transition parameterless `@content` projection in foreign components
from eager DOM creation to lazy evaluation. Previously, projecting
content into a foreign component eagerly instantiated the embedded view
and created DOM nodes, causing unnecessary resource consumption if the
content was hidden or unmounted.

With this change, runtime content instructions (`ɵɵforeignContent` and
`ɵɵforeignContentFn`) pass lazy producer callbacks directly through the
foreign component's configured `contentAdapter`. View creation and
teardown registration occur lazily when the external framework evaluates
the adapted producer.

`foreignImport` now requires a third argument, `contentAdapter`,
specifying how Angular content producer callbacks are adapted for the
target external framework.
2026-06-29 14:22:48 -07:00
Hien Pham d109cc5e9d docs: update Vitest configuration option from configFile to runnerConfig 2026-06-26 10:36:49 -07:00
Angular Robot 9d6966800f build: update all github actions to v7
See associated pull request for more information.
2026-06-26 10:36:11 -07:00
Bhuvansh855 9142712e06 docs: reorder streaming resources description 2026-06-26 10:35:28 -07:00
Bhuvansh855 9c9ead95d6 docs: document resource stream usage 2026-06-26 10:35:28 -07:00
Charles f7cb609770 docs: streamline and update mcp server setup documentation
Update and streamline the Model Context Protocol (MCP) server setup guide. This includes revising tool descriptions, replacing multiple experimental tools with a single target runner option, updating configurations for supported IDEs, and removing obsolete setup sections.
2026-06-26 10:34:37 -07:00
Karim Daher db2101c994 docs: disable overlay close-on-escape in Aria menubar examples
The Aria menubar examples render each menu in a `cdkConnectedOverlay`,
which detaches the top-most overlay on every Escape keypress
(`disableClose` defaults to `false`). The top-level menus are always
attached, so a detached overlay never reattaches and its `viewChild`
reference becomes `undefined`. Holding Escape detaches the overlays one by
one, permanently breaking menus such as "Insert" and "Format".

Set `cdkConnectedOverlayDisableClose` on the example overlays so the menu
pattern remains the single owner of open/close state, matching the
combobox and toolbar examples. Applied to the basic, disabled, and rtl
menubar examples (and their material/retro variants).
2026-06-26 10:33:21 -07:00
tmpln 74638cab84 fix(core): improve input writes migration in best effort mode
Currently, signal migration schematics in best effort mode doesn't do a very good job migrating input writes when there is a nested property access in templates.

In event handlers, no attempt is made to migrate a nested access in the left-hand-side of assignments or anything in their right-hand-side. E.g., nothing will happen here:

`(ngModelChange)="inputD.prop = $event + inputF"`.

Additionally, when a migration attempt is made, parentheses are often incorrectly placed on the parent, both in event handlers and two-way bindings:

`(ngModelChange)="inputC = $event"` is migrated to `(ngModelChange)="inputC = $event()"`.

`[(ngModel)]="inputB.prop.prop"` is migrated to `[(ngModel)]="inputB.prop().prop"`.
2026-06-26 10:30:57 -07:00
Alex Rickabaugh e9509a96aa release: cut the v22.1.0-next.3 release 2026-06-26 10:24:17 -07:00
Alex Rickabaugh 5a8bdd18f2 docs: release notes for the v22.0.4 release 2026-06-26 10:18:12 -07:00
aparziale 26b0c719ef fix(migrations): resolve migration failure when tsconfig specifies rootDir
When `rootDir` was set in a project's tsconfig (e.g. `rootDir: "src"`),
tsurge-based migrations would fail because `projectRoot` was derived from
`rootDir`, causing `rootRelativePath` to be computed relative to `src/`
instead of the workspace root. This produced paths like `app/app.ts`
instead of `src/app/app.ts`, which the DevKit tree could not resolve.

Fix by overriding `info.projectRoot` to `absoluteFrom(info.program.getCurrentDirectory())`
immediately after program creation, ensuring workspace-relative paths are
used for all tree updates.
2026-06-26 09:14:46 -07:00
kirjs 28a90e30bb release: cut the v22.1.0-next.2 release 2026-06-25 11:34:11 -04:00
Alan Agius 7f2d34a649 docs: release notes for the v22.0.3 release 2026-06-25 17:12:11 +02:00
JoostK ecd047578e fix(compiler): account for NgModule dependencies in JIT-compiled partial declarations
When partial declarations are not preprocessed to AOT by the linker, the `ngDeclareComponent`
call causes them to be compiled ad-hoc. In this mode, NgModule imports in standalone components
would be dropped, deviating from the linker. This commit changes the ad-hoc compilation of
component declarations to pass the NgModule imports along just like the linker does.

Fixes #69451
2026-06-24 14:46:43 -04:00
Matthieu Riegler f9c4b71488 refactor(compiler): desable the legacy template syntax
This disables the legacy `bind`, `bindon-`, `on-`, `let-` `ref-` syntax in g3 ONLY.
This is mostly to evaluate the blast radius
2026-06-24 14:35:13 -04:00
Matthieu Riegler 4744bab38e refactor(core): Tree shake the SimpleChanges & co.
Any application that doesn't use the `ngOnChanges` hook shouldn't pull its code.
2026-06-24 13:04:35 -04:00
Matthieu Riegler 63c7ac325d refactor(forms): widen AsyncValidatorOptions.factory
This is to accept `Resource` and not only `ResourceRef`.

fixes #69443
2026-06-24 13:03:36 -04:00
arturovt 2d33fd55ff fix(zone.js): harden zoneSymbolEventNames and patches against __proto__ key
Initialize `zoneSymbolEventNames` and `patches` with `Object.create(null)` instead of `{}`.

This is a hardening change rather than a fix for an exploitable vulnerability. Calling `addEventListener('__proto__', fn)` is not directly attacker-controlled; its presence already implies an application bug. However, if such a call does occur, the current implementation can behave unexpectedly depending on the environment.

For `zoneSymbolEventNames`, accessing `zoneSymbolEventNames['__proto__']` on a plain object invokes the inherited `__proto__` accessor and returns `Object.prototype`, which is truthy. This causes `prepareEventNames()` to be skipped, leaving `symbolEventName` undefined and eventually leading to a runtime error when `window['undefined'] = []` is executed.

In Node.js environments running with `--disable-proto=throw`, the assignment:

```ts id="z8n4qm"
zoneSymbolEventNames['__proto__'] = {};
```

throws immediately because it triggers the disabled `__proto__` setter.

The `patches` registry has a similar issue. A `__proto__` key passed to `__load_patch()` bypasses the duplicate-patch check and reaches:

```ts id="f3v7kx"
patches['__proto__'] = fn(...);
```

which invokes the `__proto__` setter and changes the prototype of the `patches` object.

Using `Object.create(null)` removes the inherited `__proto__` accessor entirely, causing these keys to behave like ordinary properties rather than interacting with JavaScript's prototype machinery.

As part of this change, `patches.hasOwnProperty(name)` is also updated to:

```ts id="n2c8wp"
Object.prototype.hasOwnProperty.call(patches, name)
```

since null-prototype objects do not inherit `hasOwnProperty`.
2026-06-24 12:19:30 -04:00
arturovt 8d31b82116 fix(upgrade): support model() signals in downgradeComponent
`model()` signals are special because they combine a signal input with a writable output through an internal `OutputEmitterRef`. During upgrade, `setupOutputs()` subscribes to that emitter to keep Angular → AngularJS two-way binding working.

The issue was that `updateInput()` could overwrite the signal property directly when `isSignal` was `false` (which happens in JIT mode and when `unsafelyOverwriteSignalInputs` is enabled). Once that happened, the original `OutputEmitterRef` was lost, so the two-way binding stopped working.

The fix detects `model()` signals at runtime by checking for both `[SIGNAL]` and a writable `.set()` method, which distinguishes them from read-only `input()` signals. When those traits are present, updates are always applied through `applyValueToInputSignal()` instead of replacing the property directly, regardless of the `unsafelyOverwriteSignalInputs` setting.

Fixes #60599
2026-06-24 12:17:35 -04:00
arturovt 97a3fd6a55 feat(router): handle null and undefined inputs in RouterLinkActive
Without this change, components that use RouterLinkActive in multiple
contexts (e.g. both a navigation menu and body content) are forced to
branch the template for every conditional input:

  @if (activeClass) {
    <a [routerLink]="href" [routerLinkActive]="activeClass"
       [routerLinkActiveOptions]="activeOptions"
       [ariaCurrentWhenActive]="ariaCurrent">
      <ng-content />
    </a>
  } @else {
    <a [routerLink]="href"><ng-content /></a>
  }

Every additional input multiplies the branching, and each @if/@else
injects unwanted comment nodes into the DOM. There is no way to
conditionally attach a directive in Angular templates, making imperative
TypeScript instantiation the only alternative.

Accepting null/undefined collapses this to a single template branch:

  <a [routerLink]="href"
     [routerLinkActive]="activeClass"
     [routerLinkActiveOptions]="activeOptions"
     [ariaCurrentWhenActive]="ariaCurrent">
    <ng-content />
  </a>

When activeClass is undefined (e.g. in content areas), the directive
stays mounted but applies no CSS classes. When it is a string (e.g. in
the navigation), normal active-class behavior applies — no branching, no
extra DOM nodes, no TypeScript workarounds.

- `routerLinkActive`: null/undefined now sets an empty class list.

- `routerLinkActiveOptions`: null and undefined are treated differently:
  - undefined → falls back to the default subset match ("not set")
  - null → explicit opt-out, link is never considered active

Closes #66233
2026-06-24 12:15:49 -04:00
SkyZeroZx 6f98f98f1f fix(service-worker): preserve referrer policy in asset requests
Preserve explicit referrer policy when the service worker reconstructs asset requests for cache-busted and redirected asset fetches.

For example, an application can load a script or image with referrerPolicy: 'same-origin' or 'origin' to limit referrer data. Dropping that policy can expose more of the current URL to that resource host.
2026-06-24 12:15:15 -04:00
SkyZeroZx 716f9eb032 fix(service-worker): preserve referrer in asset requests
Preserve referrer metadata when the service worker reconstructs asset requests for cache-busted and redirected asset fetches.

For example, an attacker with access to asset host logs could receive a reset token embedded in a page URL if the reconstructed request falls back to default referrer behavior instead of carrying referrer: ''.
2026-06-24 12:15:15 -04:00
aparziale 8b2785b597 fix(compiler-cli): report diagnostic instead of crashing on malformed host binding
`parseHostBindings` throws plain `Error`s for malformed host bindings
(e.g. a property binding with a non-static value, as can happen while
editing in the language service). These were uncaught during directive
analysis, crashing the compiler and the Angular Language Service.

Wrap the call and surface the error as a `FatalDiagnosticError` so it
becomes a diagnostic and analysis can complete normally.

Fixes #69106
2026-06-24 12:14:23 -04:00
Kam 12fcec8ce9 docs(forms): clarify debounce('blur') usage with custom FormValueControl
A custom FormValueControl only participates in debounce('blur') if it emits
the touch output on the native blur event. This was undocumented, and the
touch name reads like a focus event, so users wired it to (focus) and
blur-based debouncing silently did nothing.

Add a dedicated guide section with a working example, link the debounce API
reference to it, and clarify the touch JSDoc that it must fire on blur, not
focus.

Fixes #69370
2026-06-24 11:38:48 -04:00
Modeste ASSIONGBON edea40b5a0 docs: add doc to focusBoundControl feature 2026-06-24 11:26:26 -04:00
cexbrayat a3a9308894 docs: clarify signal forms limit metadata keys
Explain that MIN and MAX are selection keys which point to the type-specific limit metadata keys, such as MIN_NUMBER, MIN_DATE, MAX_NUMBER, and MAX_DATE.

Also list minDate() and maxDate() alongside min() and max() in the Signal Forms metadata docs, so the validator tables match the actual metadata model.
2026-06-24 11:25:56 -04:00
Shuaib Hasan Akib 64bb7adda0 docs: standardize padding and margin for insert-container 2026-06-24 11:25:23 -04:00
Saurabh Singh 7057b1257f docs(core): document resource chaining with chain() in params context
Adds a 'Chaining resources' section to the resource guide covering:
- Basic usage of chain() to depend one resource on another
- Status propagation for all ResourceStatus values (idle, loading,
  reloading, error, resolved, local)
- Chaining vs reading .value() directly, shown as an avoid example
- Guidance on passing the chained value directly as params

Also adds an @see link from ResourceParamsContext to the new section.

Closes #69329
2026-06-24 11:23:49 -04:00
arturovt ea177257e9 docs: add error guide for NG05102
Adds an error reference page for NG05102 (UNSUPPORTED_EVENT_TARGET) explaining
what triggers it and how to fix it. Also marks the error code as negative (-5102)
so that in dev mode the error message automatically links to the new guide page
on angular.dev/errors, consistent with other documented runtime errors.
2026-06-24 10:58:27 -04:00
SkyZeroZx f76e8a98c1 fix(http): prevent caching of responses with Set-Cookie headers
Skip HttpTransferCache serialization for HTTP responses that contain a
Set-Cookie header.

Cookie-setting responses commonly represent session-specific,
user-specific, or security-sensitive state. Serializing their bodies into
SSR TransferState can embed sensitive data into the generated HTML, where
it may be reused during hydration or replayed by a shared cache/CDN.
2026-06-24 10:57:45 -04:00
hawkgs ff115925e7 refactor(devtools): restructure profiler and directive forest code
- Rename `DirectiveForestHooks` to `DirectiveForestManager`
- Keep profiler reference standalone; move it out from `DirectiveForestHooks`/`DirectiveForestManager`
- Convert profiler-specific `IdentityTracker` behavior to a more generalized one
- Separate timing API functionality from the `DirectiveForestHooks`/`DirectiveForestManager` initialization fn
- Reorganize files; rename `/hooks` to `/profiling`
- Use concrete types for directive and component instances (incomplete coverage; based on `any` at the moment)
- Other more minor changes
2026-06-24 10:57:08 -04:00
Matthieu Riegler 826017dd31 refactor(compiler): Move the attribute comment to the HTML AST
This is to help the support for comment formating by third-party tools like prettier.
2026-06-24 10:56:34 -04:00
Angular Robot 295dad7389 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-24 10:48:36 -04:00
Angular Robot d7d6a08074 build: update dependency node to v22.23.1
See associated pull request for more information.
2026-06-24 10:36:02 -04:00
Alan Agius b8d40c835b build: disable pnpm dependency verification during automated PR merges
Trying to unblock caretaker.
2026-06-24 10:34:12 -04:00
Angular Robot 681148c674 build: lock file maintenance
See associated pull request for more information.
2026-06-23 15:00:31 -04:00
yamanerkam af14ce16cf fix(docs-infra): keep footer headings on a single line
The "Community translations" column heading wrapped to two lines while
the other footer headings stayed on one. Add a `white-space: nowrap`
rule on the footer headings, scoped to the wide (4-column) layout. The
breakpoint is driven by a shared `$columns-breakpoint` variable so the
nowrap rule and the grid's 2-column collapse stay in sync.
2026-06-23 14:59:36 -04:00
Alan Agius 06e9da4428 docs: document support for standard forwarded proxy header
Update the security guide to document that the Angular SSR request handling pipeline now supports and validates the standard RFC 7239 `Forwarded` header.

Previously, only non-standard `X-Forwarded-*` headers were supported for resolving proxy-forwarded protocols, hosts, and ports. With this update:
- The standard `Forwarded` header parameters (such as `host` and `proto`) are validated and take precedence over corresponding `X-Forwarded-*` headers when trusted.
- The `trustProxyHeaders` option and `NG_TRUST_PROXY_HEADERS` environment variable can be configured to trust the `Forwarded` header.

For more details on the implementation, see the corresponding PR:
https://github.com/angular/angular-cli/pull/33406
2026-06-23 14:16:51 -04:00
Kristiyan Kostadinov 91d168e74b fix(core): avoid uncaught promise errors in injectAsync prefetching
Fixes a minor issue where the `preload` function in `injectAsync` might cause an uncaught promise error.

I also fixed that in `onIdle` we were passing the wrong function into `assertInInjectionContext`.
2026-06-23 12:57:26 -04:00
yamanerkam 7421124956 docs: remove space before question mark in landing page heading
The bottom CTA heading on the landing page read "Want to learn more about
Angular ?" with a space before the question mark, while the matching heading
higher up the page correctly had no space. Removed the space so both read
"Want to learn more about Angular?".
2026-06-23 12:56:01 -04:00
arturovt dead64fbdb docs: add error guide for NG05101
Adds a new error reference page for NG05101 (NO_PLUGIN_FOR_EVENT),
which is thrown when no registered EventManagerPlugin supports the
event name passed to addEventListener. The page covers the two common
causes: a typo in the event binding and a missing plugin provider.
2026-06-23 11:25:48 -04:00
SkyZeroZx 7fc46ed3a1 docs: Add docs for markAsTouched with skipDescendants 2026-06-23 11:22:05 -04:00
Angular Robot e5d7b3a47b build: update dependency node to v22.23.0
See associated pull request for more information.
2026-06-23 10:45:43 -04:00
yamanerkam a4e9ff1e0c docs: add missing space before decorator link in components guide
The `@Component` inline-code span was directly adjacent to the
`[decorator](...)` link, rendering as a mashed-together token in the
source. Added a space so it reads "A `@Component` [decorator] that..."
as intended.
2026-06-23 09:48:16 -04:00
aparziale 69ac1d5ee8 docs: show selected menu item visually in context menu example
Replace console.log with a lastAction signal and render the result in a styled <p> element with a fade-in animation.
2026-06-22 16:46:53 -04:00
Kristiyan Kostadinov 792edaba48 refactor(migrations): account for inheritance in service migration
Updates the `@Service` migration to account for inheritance when determining if a class can be migrated.
2026-06-22 16:34:50 -04:00
Kristiyan Kostadinov c75ff0255c feat(migrations): add migration from injectable to service
Sets up an automated migration to convert `@Injectable` usages to `@Service`.
2026-06-22 16:34:50 -04:00
Kam 8b1726a1cf docs(forms): update package docs for Signal Forms graduation
After #68581 graduated the Signal Forms APIs to public API and #68654 removed
the experimental warnings from the Signal Forms documentation in adev, the
package READMEs still framed the API as experimental.

Update `packages/forms/signals/PACKAGE.md`: drop the experimental title and
intro, remove the now-shipped entries from "Not yet supported" (interop with
reactive/template forms and strongly-typed binding to UI controls), and remove
the remaining experimental and exploratory wording from the FAQ.

Update `packages/forms/PACKAGE.md`: it listed only two ways to build forms
(reactive and template-driven). Add signal forms as the third.

Fixes #68724
2026-06-22 16:29:18 -04:00
Angular Robot 089b1d1b9f build: update bazel dependencies
See associated pull request for more information.
2026-06-22 16:28:43 -04:00
Kam 642165f6fc fix(docs-infra): remove white flash on example viewer tab labels
The code tabs rendered by the example viewer (e.g. the npm/pnpm/yarn/bun
install tabs) paint their active label as transparent text clipped to a
gradient. Material's MDC tab styles add `transition: color 0.15s linear`
to `.mdc-tab__text-label`, plus a 100ms delay on the active tab. Because
that transition animates `color` from the solid label color to
transparent, the solid color stays visible on top of the gradient for
~100ms when a tab is activated, which reads as a white flash.

Disable the transition on these labels so the color switches instantly,
and target `.mdc-tab__text-label` directly (instead of a generic `span`)
so `color: transparent` drives the gradient clip cleanly.
2026-06-22 16:27:57 -04:00
Angular Robot a286a328a4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-22 16:11:26 -04:00
Angular Robot 738479f21c build: update pnpm to v11.8.0
See associated pull request for more information.
2026-06-22 16:08:41 -04:00
Kam 50bb0d6bfe fix(docs-infra): prevent inline code in table headers from wrapping mid-word
When a documentation table has a wide content column, the narrow header
columns get squeezed and inline-code header labels break mid-word at
their hyphens. On the MCP server tools page this rendered the `local-only`
and `read-only` column headers as `local-` / `only` and `read-` / `only`.

Apply `white-space: nowrap` to `code` inside `th` so header tokens stay on
a single line. The rule is scoped to headers, whose labels are always
short, so long code signatures in body cells continue to wrap and no
table gains a horizontal scrollbar.
2026-06-22 16:05:44 -04:00
Kam aa7d9fcc61 fix(devtools): restore build under stricter ts_project deps
The rules_angular bump in #69410 made ts_project require every `deps`
entry to provide the JsInfo provider. `esbuild_base` listed
`//packages:package_json` in its deps, but `esbuild-base.config.mts` never
imports or reads package.json, so the dependency is unnecessary and now
breaks analysis (`//packages:package_json` is a `copy_to_bin` target that
provides only DefaultInfo). Remove it.
2026-06-19 11:37:17 +02:00
Kam 350763d84a fix(docs-infra): restore adev build under stricter ts_project deps
The cross-repo dependency update in #69410 bumped rules_angular, whose
ts_project now requires every entry in `deps` to provide the JsInfo
provider. Two adev targets passed deps that don't, so `bazel build
//adev:build` fails analysis and the adev CI check has been red on main
since that PR.

Make generate_nav_items return JsInfo (with the generated routes.json as
its sources) so navigation-entries can keep importing routes.json through
its deps. Also drop the spurious deps entry on llms_lib: llms.mts reads
llms-list.md at runtime via readFile rather than importing it, and the
file is already provided to the binary via data.

Fixes #69429
2026-06-19 11:37:17 +02:00
Angular Robot 7e1fcd4ce6 build: update all github actions to v6.0.9
See associated pull request for more information.
2026-06-18 14:22:31 -04:00
rudzikdawid 69a00043a4 docs(docs-infra): add missing readonly property to combobox guide
PR angular/components#33364 restored the `readonly` property for the
combobox, but the documentation was not updated to reflect this change.
This commit adds the missing `readonly` input and its description to
the Inputs / Model table in the combobox guide.
2026-06-18 14:18:36 -04:00
yamanerkam e77a8a0c7a fix(docs-infra): align the page title with its edit action
The page title row (`.docs-page-title`) relied on the default flex
alignment, so the edit icon next to the title did not line up with the
title text. Add `align-items: baseline` so the icon sits on the title's
baseline.
2026-06-18 14:06:22 -04:00
Joey Perrott ebe92fe291 ci: update dev-infra release workflow SHA
Updates the reusable release workflow reference to point to the latest merged commit in dev-infra containing the resilient publish fixes.
2026-06-18 14:05:30 -04:00
Jessica Janiuk a849b6fbfd Revert "fix(core): escape overlapping comment delimiters in escapeCommentText"
This reverts commit ea1a3ed64c.
2026-06-18 12:34:25 -04:00
Angular Robot 1566442a0d build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-18 12:26:16 -04:00
yamanerkam ffcc8eee98 fix(docs-infra): correct select dropdown scrolling, sizing, and selection
Several issues in the shared docs `Select` component (used by the API
reference package filter):

- The options list never scrolled: its element used a class with no styles,
  so the intended max-height/overflow rule was dead. Point it at the styled
  class so long lists scroll within the popover.
- Selecting an option now closes the popup instead of leaving it open.
- Clip the trigger and popover corners (overflow: hidden) so their rounded
  borders render cleanly, and align the popover width with the trigger.
- Drop the selected-option checkmark. The component is single-select and
  already marks the selection with a highlight, so the tick was misleading.
- Remove the unused `disabled` input.
2026-06-18 10:52:35 -04:00
yamanerkam e7a4e25318 docs: use the @Service decorator in the first-app and signals tutorials
Update the services in the first-app and signals tutorials to use the
`@Service()` decorator instead of `@Injectable({providedIn: 'root'})`.
This affects `HousingService` (first-app steps 10-14) and `CartStore`
(signals step 7).
2026-06-18 10:48:02 -04:00
Matthieu Riegler c23ddd6a99 docs(docs-infra): remove deprecated ts flags
This fixes the playground & tutorials
2026-06-18 15:29:39 +02:00
Jessica Janiuk 302dd0f7c6 release: cut the v22.1.0-next.1 release 2026-06-17 14:16:07 -07:00
Jessica Janiuk f540400ac1 docs: release notes for the v22.0.2 release 2026-06-17 14:09:45 -07:00
Angular Robot e35e4a9f67 build: update cross-repo angular dependencies to 1ce5d68
See associated pull request for more information.
2026-06-17 13:57:40 -07:00
Joey Perrott 45192ba749 ci: update dev-infra reference to new commit SHA
Updates the reusable release workflow reference to use the new commit SHA 1ce5d6899a2634fccf021a84656026bed0acbe16 from angular/dev-infra PR 3796.
2026-06-17 13:10:43 -07:00
Cameron Smick ae6d8dae75 refactor(core): add childSignalProp to ReactiveNodeKind
Add `childSignalProp` to `ReactiveNodeKind` in order to consolidate `ReactiveNodeKind` types and enable Client-Only Wiz to use it.
2026-06-17 13:03:13 -07:00
arturovt 8cf7731468 fix(core): guard against DOM clobbering in declareExperimentalWebMcpTool
Previously, the modelContext truthiness check could be bypassed via DOM
clobbering (e.g. `<form id="modelContext">`), causing a truthy HTMLElement
to pass the guard and then throw when `registerTool` was called on it.

Replace the truthiness check with a duck-type check that asserts
`registerTool` is a function, rejecting both absent and clobbered values.
2026-06-17 13:02:10 -07:00
Andrew Scott 1e79dd3140 refactor(router): Add handling for ActivatedRoute-scoped injector
Add handling in navigation for creating and destroying injectors scoped
to `ActivatedRoute` life.
The code for creating the injectors is certainly more complicated
than it _could_ be since there's no actual feature built around this yet.

Keeps as much implementation code tree-shakeable as possible:
Raw size: +764 bytes
Gzipped size: +182 bytes
2026-06-17 11:39:13 -07:00
Joost Koehoorn 327744ac17 perf(core): detect existing signal dependency without checking all producer links
This commit addresses a scaling issue in the signal dependency graph where
the detection of duplicate dependency links would perform a linear scan across
all consumer links of all producers. The linear scan is replaced with a version
comparison of the dependency edge against the current epoch; if they are
equal the existing dependency edge is known to be valid in this epoch. This means
that the link won't be eligible for removal and therefore doesn't have to be
recreated.
2026-06-17 11:38:04 -07:00
rootvector2 ea1a3ed64c fix(core): escape overlapping comment delimiters in escapeCommentText
`COMMENT_DISALLOWED` is matched globally, so overlapping delimiter
sequences are skipped: `<!-->` only escapes the leading `<!--` and
leaves a live `-->` that can close a programmatically created comment
node early. Drop the `^` anchors so a standalone `>`/`->` is escaped
wherever it appears, which neutralizes the trailing delimiter left
behind by an earlier match.
2026-06-17 11:37:08 -07:00
Joey Perrott ea18ab24dd ci: add id-token: write permission to release workflow
Adds id-token: write permission to the release workflow to allow the called reusable workflow to generate NPM provenance metadata during publishing.
2026-06-17 10:32:27 -07:00
Angular Robot 6bd2cea404 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-17 10:31:15 -07:00
aminesbdev a89ab78a11 docs(docs-infra): update environment configuration examples and remove production flag 2026-06-17 10:01:36 -07:00
aminesbdev 0a06167208 docs(docs-infra): add environment runtime configuration
Add a new reference explaining Angular environment configuration strategies,
including both build-time and runtime approaches.

Register the reference in SKILL.md so it is discoverable by the skill system.
2026-06-17 10:01:36 -07:00
Angular Robot 2d2d5fc362 build: lock file maintenance
See associated pull request for more information.

Closes #69367 as a pr takeover
2026-06-17 09:12:30 -07:00
Andrew Scott a5ee50beac refactor(compiler): correct TcbInvalidReferenceOp initializer
initializer should use null! as any rather than simply '= any'
2026-06-17 08:14:51 -07:00
Joey Perrott a7d142913f ci: update reusable release workflow target SHA, pass robot key, and downgrade permissions
Updates the reusable workflow reference to target the merged dev-infra commit e9faacd5b4df391f59989b6fb448b2c24115d592. Passes the ANGULAR_ROBOT_PRIVATE_KEY secret as angular-robot-key. Downgrades default contents permission to read as write access is handled by the App token in the custom action.
2026-06-17 08:10:59 -07:00
Joey Perrott 182fbb8476 ci: introduce GHA release publish workflow
Introduce the caller GitHub Actions workflow for release publishing, which delegates the build and publish steps to the centralized reusable workflow in dev-infra. This targets the merged reusable workflow in dev-infra by SHA.
2026-06-17 08:10:59 -07:00
Angular Robot 9378577bd7 build: update pnpm to v11.7.0
See associated pull request for more information.
2026-06-17 08:07:51 -07:00
rudzikdawid 02d6b436f1 fix(docs-infra): increase SSR fetch limit to prevent 404 on page reload
Navigating to specific ARIA guide pages directly or via hard refresh
causes a 404 error because the payload exceeds the default SSR fetch
limit. This commit increases the maxResponseBodySize to 2MB.
2026-06-17 08:03:54 -07:00
Alex Rickabaugh 86ade07de6 refactor(compiler): add support for @Input transforms under isolatedDeclarations
Adds support for `@Input` transform functions in isolated declarations mode (`emitDeclarationOnly: true`), allowing components and directives to specify `transform` functions without triggering fatal compiler errors.

Synthesizes the `ngAcceptInputType_` write type syntactically:
- For referenced functions (`transform: booleanAttribute`), emits `Parameters<typeof booleanAttribute>[0]`, relying on downstream template type checking to resolve the type.
- For inline functions (`transform: (v: string) => boolean`), extracts `parameters[0].type` directly from the local TypeScript AST.
2026-06-16 10:27:18 -07:00
Alex Rickabaugh 5d2b1c4100 refactor(compiler): add support for host directives under isolatedDeclarations
Removes restrictions around using external references and local directives in `hostDirectives` under isolated declarations mode (`emitDeclarationOnly: true`).

By wrapping the host directive reference in a `WrappedNodeExpr`, TypeScript's declaration emitter seamlessly emits `typeof hostReference.node`, preserving existing imports or local identifiers exactly as authored. Also adds support for translating `PropertyAccessExpression` inside `WrappedNodeExpr` into `QualifiedName` for `.d.ts` emission, ensuring namespace imports (`import * as n from './dir'`) are preserved correctly.
2026-06-16 10:27:18 -07:00
SkyZeroZx 0152e3cbdf fix(core): treat iframe credentialless as security-sensitive
Mark the iframe `credentialless` attribute as security-sensitive so dynamic
bindings are handled consistently with other iframe attributes that affect the
initial navigation, such as `sandbox`, `allow`, `referrerPolicy`, `csp`, and
`fetchPriority`.

Because `credentialless` must be present before the iframe starts loading to
affect the navigation’s credential mode, late dynamic updates can leave the final
DOM looking correct while the initial request was not loaded credentiallessly.
2026-06-16 09:05:53 -07:00
yamanerkam cbccd368af docs: use the @Service decorator in the learn-angular DI tutorial
The "Creating an injectable service" tutorial introduced services with
`@Injectable({providedIn: 'root'})`, even though the essentials guide and
the in-depth dependency injection guides have already moved to the newer
`@Service` decorator. This left the tutorial out of step with the rest of
the documentation.

Update steps 19 and 20 to use `@Service()`. Because `@Service()` is an
ergonomic shorthand for `@Injectable({providedIn: 'root'})`, the examples
behave identically while teaching the recommended modern API. The step 19
README is reworked to match: it drops the now-unnecessary `providedIn`
configuration step and adds a note linking to the in-depth services guide
for the `autoProvided: false` opt-out.
2026-06-16 08:49:04 -07:00
Kristiyan Kostadinov 28cb15a2bb fix(core): prevent unsubscribe during emit from throwing off other listeners
Fixes that when a listener unsubscribes from an `output` within its own callback, it was preventing subsequent listeners from running.

These changes fix the issue by not mutating the array while the emit loop is running, but replacing the listener with `null` and coming back later to remove it.

Fixes #69325.
2026-06-16 08:29:32 -07:00
Matthieu Riegler 74fa0588b1 refactor(devtools): ensure code is escaped
By stringifying twice we ensure the code is escape before building the string template.
2026-06-16 08:25:35 -07:00
Angular Robot 383a42a89f build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-16 08:18:45 -07:00
Andrew Scott 83622ee519 refactor(compiler-cli): Export indexer API for use in hybrid analysis
exports indexer API for use in hybrid analysis
2026-06-15 11:53:36 -07:00
Angular Robot 01e99d8a32 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-06-15 11:18:08 -07:00
Andrew Scott 21fccd4038 refactor(compiler-cli): Change indexComponent file to be fileUrl
We do not need ParseSourceFile which contains the whole content. Only the file url is ever used.
2026-06-15 10:56:51 -07:00
Matthieu Riegler 471dcb42ca refactor(compiler): Collect in-element comments
PR #67179 forgot to implement that part.
2026-06-15 10:54:06 -07:00
SkyZeroZx 98f42eaaae fix(core): avoid caching missing locale data
Only cache locale data loaded from the global locale registry when an actual locale entry is found.

This prevents attacker-controlled missing locale identifiers from being retained indefinitely in SSR when locale lookup falls back to a parent locale or the built-in English locale, avoiding unbounded process memory growth in locale-aware pipes and formatters.
2026-06-15 10:53:08 -07:00
Alan Agius 417a4071a7 fix(compiler): restrict possible event handler check to property names longer than 2 characters
Previously, the compiler disallowed translation of any attribute starting with 'on' for security reasons. This incorrectly disallowed translation of the 'on' attribute itself, which is not an event handler.

This commit introduces `isPossibleEventHandler` to verify that the property name has a length greater than 2 in addition to starting with 'on'. This allows attributes like 'on' to be translated while still correctly disallowing actual event handlers like 'onerror', 'onclick', etc.
2026-06-15 09:23:49 -07:00
Andrew Scott 2112edefe1 refactor(core): ɵɵgetInheritedFactory should accept abstract type
An abstract component or directive can extend another class, meaning
ɵɵgetInheritedFactory needs to allow abstract
2026-06-15 09:22:35 -07:00
Angular Robot 958c198aa3 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-15 09:18:49 -07:00
Kam 4ba8ba4ef2 fix(docs-infra): align homepage banner and search field
The homepage hero lays out the announcement banner and the search field on
the same flex row. The `.search-field` wrapper was a plain block, so its
`docs-text-field` kept its intrinsic height instead of filling the row,
leaving the two pills at different heights and vertically misaligned.

Make `.search-field` a flex container so the search control stretches to the
row height and matches the banner.
2026-06-15 09:15:29 -07:00
Kam 50e7f3a1cd fix(docs-infra): center social and theme menus under their triggers on tablet
On tablet the social and theme mini-menus didn't line up with the buttons that
open them.

All three mini-menus now share one tablet positioning rule on `.adev-mini-menu`
that centers each panel under its trigger, with `--social`/`--theme`/`--version`
modifiers selecting the anchor; the version picker's on-screen behavior is
unchanged. The social trigger also gains `aria-controls` + a matching menu `id`
for a11y parity with the theme trigger.
2026-06-15 08:59:18 -07:00
Kam 43acead06d fix(docs-infra): use a facade for docs-video to fix Firefox embeds
Follow-up to #69205. After switching adev's COEP to `credentialless`, the
cross-origin YouTube iframe in `<docs-video>` loads in Chromium and Safari but
not Firefox, whose `credentialless` policy does not extend to nested frames. The
result was a COEP error screen instead of the player.

Render `<docs-video>` as a lightweight thumbnail facade instead of embedding the
iframe directly. The thumbnail is a cross-origin subresource, so it loads under
`credentialless` in every browser. `DocViewer` then upgrades the facade to the
inline player on hydration in browsers that can load the embed (Chromium,
Safari), preserving the previous behavior there. On Firefox the facade stays a
plain link that opens the video on YouTube (with autoplay), which replaces the
error screen.

The thumbnail uses `maxresdefault` and falls back to `hqdefault` when a video
has no max-resolution image.
2026-06-15 08:58:00 -07:00
Matthieu Riegler 3b8bb7219b docs: add item about the resource breaking change.
In #67382 we changed how values are resolved which ended up being a breaking change for some unit tests.

fixes #69360
2026-06-15 08:57:02 -07:00
kirjs c0e2364f12 docs(forms): use touch.emit() in custom controls example 2026-06-15 08:56:11 -07:00
Angular Robot 20fb11bdda build: update pnpm to v11.6.0
See associated pull request for more information.
2026-06-15 08:54:16 -07:00
whit33y 40f7fbdccb docs: clarify value attribute on radio/checkbox inputs is allowed with formField 2026-06-12 10:16:44 -07:00
aparziale 58efd86c78 fix(migrations): migration skip any target are not build or test
Fix migration behaviout that skip any target are not build or test

Fixes #66865
2026-06-12 09:24:44 -07:00
Alan Agius 32d7315094 refactor: optimize dom security schema lookups
Restructure the security schema map to index by property name instead of tag name, improving lookup efficiency.
2026-06-12 09:20:36 -07:00
hawkgs db677a4349 fix(docs-infra): stabilize html element scroll gutter
Stabilize `<html>` scroll gutter.

Fixes #69036
2026-06-12 09:19:32 -07:00
hawkgs 91ab7c6dea fix(docs-infra): add explicit font styles to docs-primary-btn
Add font family, size and weight to the `.docs-primary-btn`. This guarantees that applying the class to non-button elements, like anchors, will results in the same visual representation.
2026-06-12 09:08:02 -07:00
Angular Robot a157ec51af build: update pnpm to v11.5.3
See associated pull request for more information.
2026-06-12 08:18:32 -07:00
Angular Robot 72a8b98f54 build: update cross-repo angular dependencies to 11ee1f5
See associated pull request for more information.
2026-06-12 08:16:46 -07:00
Andrew Scott 8984c59626 refactor(core): ComponentDef should allow abstract types too
d1539a8513 incorrectly assumed components wouldn't be abstract but
it is still possible (though probably should be an abstract directive instead).
2026-06-11 13:08:09 -07:00
Aleksander Bodurri 985fd78818 docs(devtools): document the injector tree visualization
Add an internals doc covering how the injector tree is built from the directive forest's resolution paths, rendered with d3, and how injector data is read from the DI debug APIs.
2026-06-11 13:07:08 -07:00
Jessica Janiuk 782157dfd6 docs: release notes for the vscode extension 22.0.1 release 2026-06-11 13:05:06 -07:00
Jessica Janiuk dcc4fe06b9 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-11 13:04:18 -07:00
Kai Guo 6b5616b2c7 fix(core): preserve leave animation for sibling instances sharing a TNode
`animate.leave` was skipped — the element was removed from the DOM
synchronously instead of running its leave animation — whenever a
sibling instance of the same template entered in a different DOM parent
during the same change-detection tick (e.g. an exclusive-expansion
accordion or nav where opening section B collapses section A).

`leavingNodes` is keyed by `TNode`, which is shared by every instance of
a template. When a node was inserted, `cancelLeavingNodes` force-removed
any tracked leaving node whose DOM parent differed from the entering
node's parent (the `leavingParent !== newParent` branch added to
de-duplicate a dynamic component re-rendered into a fresh overlay pane).
For two distinct live sibling instances that merely share a `TNode`,
"different parent" is the normal situation, so the still-animating
sibling was ripped out.

Track the declaration view of each leaving element alongside it, and
only perform the cross-parent removal when the entering element belongs
to the same declaration view as the leaving one — i.e. the same logical
view re-rendered, the case the branch was written for. Two distinct
instances of a shared template have different declaration views, so
their `animate.leave` is now left to run to completion.

This preserves the dynamic-component/overlay de-duplication (#67032) and
the drag-and-drop node-move rescue (#67361), which are unchanged.

Fixes #69291
2026-06-11 10:38:57 -07:00
Hexix23 a6c7fc5c13 fix(http): distinguish repeated transfer cache params
Serialize transfer cache request parameters without comma-joining repeated values so distinct HttpClient requests cannot reuse the same cached response.
2026-06-11 09:59:27 -07:00
arturovt fd7c2daf4d fix(zone.js): harden zoneSymbolEventNames against __proto__ key (defense-in-depth)
Initialize zoneSymbolEventNames with Object.create(null) instead of {}.

This is hardening only. addEventListener('__proto__', fn) is not
directly attacker-controllable — its presence in an application is
itself an application bug and a prerequisite for any issue here.

Without this change, if that application bug exists, two unexpected
behaviors follow depending on environment:

Browser: zoneSymbolEventNames['__proto__'] reads the __proto__ getter
and returns Object.prototype (truthy), bypassing prepareEventNames.
symbolEventName resolves to undefined and window['undefined'] = []
throws TypeError.

Node.js + --disable-proto=throw: the assignment
zoneSymbolEventNames['__proto__'] = {} inside prepareEventNames
triggers the disabled __proto__ setter and throws.

Using Object.create(null) removes the __proto__ accessor from the
map so the key is treated as a plain missing property in both cases.
2026-06-11 09:41:07 -07:00
rootvector2 a69e56df71 fix(common): escape anchor fragment in shadow DOM name selector
`findAnchorFromDocument` interpolates the raw url fragment into
`[name="${target}"]` for the shadow DOM lookup, so a fragment reachable
through the router when `anchorScrolling` is on can break out of the
attribute selector and make `querySelector` throw or match unrelated
nodes, and it also breaks legitimate anchor names containing a quote.
Wrap the value in `CSS.escape` so it stays a single attribute-value token.
2026-06-11 09:37:27 -07:00
Alan Agius 030916caa6 build: update deprecation message for @angular/animations to include documentation link
Add link to the `@angular/animations` deprecation warning.
2026-06-11 09:34:44 -07:00
hawkgs 78b12b3dd7 refactor(devtools): minor improvements of the transfer state UI
The change can be treated as a continuation of #68535.

- Make the table header sticky
- Reduce slightly the table density in order to equalize it with the rest of the UI
- Reduce the font size of the type pills
- Change the position of the filter clear button to match with the rest of the filter inputs
- Add a "No such key" label when there are no data rows as a result of filtering
2026-06-11 09:30:15 -07:00
hawkgs fd33b6e4e9 refactor(devtools): improve public API naming of the visualizers
Improve the name of the public methods of the visualizers by using common terms like "highlighted". This should, hopefully, clear up some ambiguities that came with the term "selected". Additionally, clean up some CSS class names.
2026-06-11 09:29:28 -07:00
Angular Robot 393a71f4ad build: update all non-major dependencies
See associated pull request for more information.
2026-06-11 09:28:12 -07:00
Matthieu Riegler 59e2041847 docs(docs-infra): Update navigation status 2026-06-11 09:24:28 -07:00
Edu 6b3e46a872 refactor(devtools): rename element to tagName and keep nativeElement flat
This refactoring renames the 'element' (tagName string) property of DevToolsNode to 'tagName' for clarity, as 'element' was ambiguous.
It also restores 'nativeElement' as a flat property (undoing the nesting introduced previously) because there are cases (like control flow blocks) where a tag name is present without an associated DOM node, making nesting inappropriate.
2026-06-11 09:22:55 -07:00
Angular Robot 71bb19d772 build: lock file maintenance
See associated pull request for more information.
2026-06-10 15:43:00 -07:00
Andrew Scott 6f3e832b1a release: cut the v22.1.0-next.0 release 2026-06-10 13:40:57 -07:00
Andrew Scott 9f4b3dc8eb docs: release notes for the v22.0.1 release 2026-06-10 13:19:33 -07:00
Andrew Scott 7e94ab919d docs: release notes for the v21.2.17 release 2026-06-10 13:02:36 -07:00
Doug Parker daadb3863e release: bump Angular DevTools version to 1.16.0 2026-06-10 12:55:42 -07:00
Andrew Scott e867c03e9a docs: release notes for the v20.3.25 release 2026-06-10 12:30:57 -07:00
Matthieu Riegler c092a002e4 fix(http): pass down the reportUploadProgress and reportDownloadProgress on post/patch requests
The `addBody` function did not pass the argument correctly

fixes #69241
2026-06-10 11:37:45 -07:00
SkyZeroZx 274d1d2dcc docs: add caching guidance for resource data with SSR 2026-06-10 11:27:42 -07:00
Andrew Scott fbe807ca12 fix(vscode-extension): resolve relative workspace tsdk paths to absolute
Resolve the approved relative workspace tsdk path to an absolute path by checking workspace folders. This ensures the path is correctly resolved on the server side.

Fixes #69276
2026-06-10 11:09:55 -07:00
Matthieu Riegler f2b642b10a docs(docs-infra): remove test related deps
They were unused. (it makes maintenance less confusing)
2026-06-10 11:08:57 -07:00
Andrew Scott 54112d9393 refactor(compiler): Remove 80 char limit on AbstractEmitterVisitor
This limit breaks ts-ignore comments when using this for our source->source transform.
Rather than overridding it there, it's just removed here since we don't care about the limit
2026-06-10 10:57:26 -07:00
aparziale 8854f2d476 docs: update webpack-based system docs
Update webpack-based system docs

Fixes #69279
2026-06-10 10:54:41 -07:00
Andrew Scott d25d2e1524 refactor(core): Update registerNgModuleType to support codegen typechecking
Updates types and adds test for source->source transformation with tsc downstream
2026-06-10 10:52:55 -07:00
Andrew Scott a7e7a2cf05 refactor(forms): fix initWebMcpForm description to be required
updates from breakage in https://github.com/angular/angular/commit/c121407c0da2456543a54822941d71a75490b703
2026-06-10 10:51:15 -07:00
Doug Parker 492e3a2a1f test(core): fix AI tools test flake
This test flakes occasionally because it is called in production when a platform is created and unregistered when a platform is destroyed. However, not all tests properly clean up their platforms, meaning we can accidentally leak platforms between tests. If this happens, we end up have an event listener created from the production code path and a second event listener from the test. When the test emits the event, both listeners respond and it causes too many responses which fails the test.

Ideally, all tests would clean up the platforms correctly, but this seems difficult to guarantee for all Angular tests and is likely to break over time. The simplest solution is just destroy any leaked platform before the test starts. It's a bit elegant, but the safest option.
2026-06-10 10:29:00 -07:00
Angular Robot 7be0647e1f build: update dependency @vscode/test-electron to v3
See associated pull request for more information.
2026-06-10 10:25:20 -07:00
Edu 781cc84db0 refactor(devtools): convert router details panel to description list
Convert the router details panel in DevTools to use a description list (<dl>) instead of a table. This is semantically more correct for key-value metadata and improves accessibility.
2026-06-10 10:23:23 -07:00
SkyZeroZx e640692452 fix(core): validate lowercase SVG animation attribute names
Normalize SVG animation attributeName lookup to also recognize lowercase attributename before allowing dynamic animation value bindings.

Add runtime and platform-server SSR regression coverage for lowercase attributename retargeting.
2026-06-10 10:22:29 -07:00
Hexix23 6c41f5ca01 fix(compiler): disallow i18n event attributes
Reject translated event-handler attributes so localization cannot bypass Angular event-attribute validation.
2026-06-10 10:21:33 -07:00
SkyZeroZx 2066225244 docs: deprecate XHR support for server-side rendering in HTTP docs and recommend Fetch 2026-06-10 10:20:39 -07:00
arturovt 1ec125276d fix(common): prevent prototype pollution in formatDateTime
Replace `in` operator with `Object.hasOwn` in
formatDateTime to prevent prototype pollution attacks.

The `in` operator traverses the prototype chain, meaning a polluted
Object.prototype key could be picked up as a valid replacement value.
This is especially critical in SSR environments where a single
prototype pollution attack persists across all subsequent requests in
the shared Node.js process, potentially injecting malicious content
into every user's rendered HTML.

Using `Object.hasOwn` restricts the lookup to
own properties only, blocking prototype chain traversal.
2026-06-10 10:19:28 -07:00
Matthieu Riegler 9604ecfd8b fix(forms): delay mcp reading the form model by a tick
Reading the form model on init is unsafe as it could depend on inputs (eg a required input). We need to delay the read by a tick (after the inputs are set) to ensure that values can be safely read.

fixes #69262
2026-06-10 10:14:41 -07:00
Matthieu Riegler 3927a5b271 fix(compiler): sanitize href/xlink:href attributes of any element of the MathML namespace
The ensures that future, present and past (and precated) elements of that namespace get sanitized.
2026-06-10 10:13:48 -07:00
arturovt 6cc54e5ede fix(forms): remove animationstart listener on component destroy to prevent memory leak
The `watchValidity` method in `AnimationInputValidityMonitor` was registering
an anonymous arrow function via `addEventListener` with no corresponding
`removeEventListener` call.

In V8, each closure is represented as a `JSFunction` holding a strong pointer
to a heap-allocated `Context` object containing captured variables
(`VariableLocation::CONTEXT` slots, decided at parse time by
`Scope::MustAllocateInContext`). In Blink, DOM event listeners are stored in
the element's `EventTargetData::event_listener_map` as `JSEventListener`
wrappers backed by a `v8::Persistent<JSFunction>` handle — a strong cross-heap
reference that keeps the function alive as long as the element is alive.

Because the callback passed to `watchValidity` closes over the calling
component/directive (which itself holds a reference back to the element), this
produced a cross-heap reference cycle:

```
  HTMLInputElement (Blink/Oilpan)
    └── EventTargetData → JSEventListener → v8::Persistent<JSFunction>
          └── Context → callback closure
                └── component → HTMLInputElement  ← cycle
```

Neither V8's nor Blink's GC could independently break this cycle because it
crosses the V8/Oilpan heap boundary. The element was therefore never collected
after being removed from the DOM.

The fix stores the listener in a named local variable and registers its removal
via `DestroyRef.onDestroy`, tying cleanup to the lifetime of the component that
owns the element. This ensures `removeEventListener` is called with the exact
same `JSFunction` reference, causing Blink to drop the `v8::Persistent` handle
and allowing both the function and the element to become GC-eligible.
2026-06-10 09:56:12 -07:00
Kristiyan Kostadinov 158307cd63 refactor(core): add internal utility
Sets up a utility function that we need for an internal project.
2026-06-10 09:54:35 -07:00
Matthieu Riegler f06b96d181 fix(forms): harden FormGroup control lookups against prototype shadowing
Guard FormGroup control-map presence checks with safe own-property checks to avoid inherited/prototype collisions from reserved keys such as hasOwnProperty and toString.

This prevents:
- crashes from shadowed hasOwnProperty access paths
- incorrect early-return and existence behavior for prototype-named controls

Adds regression tests for prototype-shadowed keys covering:
- register/add with toString
- contains/get with hasOwnProperty
- setControl/removeControl with toString
- FormRecord behavior with hasOwnProperty
2026-06-09 19:27:56 -07:00
Matthieu Riegler 6b0150faad refactor(migrations): Improve safeNavigationMigration heuristic
There is no need to migrate expressions with a nullish comparison.

fixes #69274
2026-06-09 17:11:55 -07:00
Andrew Scott d1539a8513 refactor(core): Fix DirectiveDefinition interface to allow abstract classes
Interface should permit abstract classes since directives can be abstract
2026-06-09 16:21:04 -07:00
Angular Robot 7541f3012f build: update pnpm to v11.5.2
See associated pull request for more information.
2026-06-09 14:55:56 -07:00
Jad Chahed 248e9c146d docs: add Signal Forms and v22 guidance to AI best-practices and llms.txt
Update the AI codegen resources for Angular v22:
- best-practices.md: OnPush is the default in v22+ (don't set it explicitly),
  recommend Signal Forms, and recommend the @Service decorator.
- llms.txt: add a Signal Forms reference, the httpResource guide, and an
  Accessibility section linking the Angular Aria overview.
2026-06-09 13:59:56 -07:00
Andrew Scott 2e4ed8027d fix(language-service): prevent external template inlay hints from appearing in TS files
Inlay hints from external templates were being incorrectly applied to
TypeScript files because the compiler was processing all templates
associated with components found in the TS file, regardless of whether
the template was inline or external. This resulted in misplaced hints
due to mismatched offsets.

This change filters the templates and host bindings processed in
getInlayHintsForTemplate to only include those that belong to the
target file being queried.

Fixes #69224
2026-06-09 13:33:15 -07:00
Kam 86cd166141 fix(docs-infra): load cross-origin video embeds under COEP credentialless
adev is cross-origin isolated (COOP same-origin + COEP require-corp) so the
embedded WebContainer editor can use SharedArrayBuffer. Under require-corp the
cross-origin YouTube iframe in `<docs-video>` only loaded in Chromium, leaving
the player blank in Safari.

Switch COEP from `require-corp` to `credentialless`. The page stays cross-origin
isolated, so the editor keeps working, but cross-origin frames are now allowed
to load, which restores the inline player in Safari as well.
2026-06-09 13:26:18 -07:00
Kristiyan Kostadinov 5829177729 fix(core): update comment for Default change detection
Updates the comment on `ChangeDetectionStrategy.Default` to mention that it's the same as `Eager`.

Fixes #69253.
2026-06-09 13:09:58 -07:00
Andrew Scott 0e16bb701f fix(core): Handle synchronous errors in PendingTasks.run function
catches synchronous errors coming out of the function passed to PendingTasks.run
2026-06-09 12:24:20 -07:00
Angular Robot 390af258bb build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-09 11:23:48 -07:00
Andrew Scott fe721868a6 fix(router): use native URL object for navigation boundary and comparison
Previously, `NavigationStateManager` relied on string-based comparisons and `.substring()` to match `NavigateEvent` URLs against internal router transitions or the application root boundary. This was brittle against trailing slashes, query parameter order variations, and sibling application URLs.

This commit updates the logic to:

- Use the native `URL` object to strictly compare `origin` and `pathname` for `appRootURL` boundaries.

- Sort `searchParams` and use `Location.stripTrailingSlash()` to robustly compare the router destination against the event destination.

- Pre-compute and store `appRootUrl` as a `URL` object to avoid redundant parsing on every navigation.
2026-06-09 11:15:15 -07:00
Angular Robot 0a9ff4ea47 build: update all non-major dependencies
See associated pull request for more information.
2026-06-09 11:07:34 -07:00
arturovt 3dd35c242c fix(common): escape CSS string-terminating characters in escapeCssUrl
The `escapeCssUrl` helper used by `NgOptimizedImage` to sanitize placeholder URLs for use in the `background-image` CSS property previously escaped only backslashes and double quotes. However, several characters that can terminate a CSS quoted string according to the CSS Syntax Level 3 specification were left unescaped, allowing a crafted placeholder URL to break out of the `url("...")` context and inject arbitrary CSS.

This change additionally escapes the following characters using CSS hex escapes:

* `U+000A` (LINE FEED) → `\A `
* `U+000D` (CARRIAGE RETURN) → `\D `
* `U+000C` (FORM FEED) → `\C `
* `U+0000` (NULL) → `\0 `

For example:

```text id="1w5vkp"
x.com/img\nx.jpg  →  x.com/img\A x.jpg
x.com/img\rx.jpg  →  x.com/img\D x.jpg
x.com/img\fx.jpg  →  x.com/img\C x.jpg
x.com/img\0x.jpg  →  x.com/img\0 x.jpg
```

The trailing space is required by the CSS tokenizer to terminate the escape sequence and prevent the following character from being interpreted as part of the escape.

The backslash replacement remains first in the chain to avoid double-escaping the backslashes introduced by subsequent replacements.
2026-06-09 10:40:20 -07:00
cexbrayat c121407c0d fix(core): require WebMCP tool descriptions
The WebMCP ModelContextTool dictionary marks description as required: https://webmachinelearning.github.io/webmcp/#modelcontexttool-dictionary
2026-06-09 10:29:11 -07:00
Matthieu Riegler bff084f203 refactor(core): harden change store access
This prevents any attack through prototype polution.
2026-06-09 10:05:53 -07:00
Kam 7d92cc8b46 fix(docs-infra): improve version picker dropdown positioning
Drops `position: absolute` from the version picker `<ul>` and tightens `max-height` to `70dvh` so the cdk-overlay-pane fits the viewport and the inner scroll reaches the last versions on mobile and desktop.
2026-06-09 09:58:21 -07:00
Alan Agius 8446e46f8b refactor(platform-server): deprecate ServerXhr
XHR support in `@angular/platform-server` is deprecated because the underlying `xhr2` library does not safely handle redirects. Specifically, it can forward `Authorization` headers on cross-origin redirects (which leaks credentials) and is susceptible to denial-of-service (DoS) via redirect loops.

DEPRECATED: XHR support in `@angular/platform-server` is deprecated. Use standard `fetch` APIs instead.
2026-06-09 09:54:16 -07:00
Matthew Beck 547d85addf ci: run benchmark comparison in isolated worktree and harden security
- Run comparison benchmark in an isolated git worktree to prevent workspace pollution and local branch conflicts.
- Harden security by passing benchmark target and SHA as environment variables to prevent shell injection, and adding '--' to bazel query and git rev-parse.
- Optimize workflow by removing pnpm caching to mitigate cache poisoning risks.
- Improve robustness of benchmark log parsing, supporting both ZIP outputs and raw directories, and safely checking for JSON reports.
- Centralize git command execution on the dev-infra GitClient for consistency.
- Add tslib to benchpress dependencies to prevent module resolution failures.
2026-06-09 09:48:50 -07:00
SkyZeroZx cd771d3712 fix(http): preserve empty referrer option in HttpRequest
Preserve `referrer: ''` when constructing and cloning HttpRequest.

An empty string is a valid Fetch referrer value and is documented by
Angular as the way to omit referrer information for sensitive requests.
The previous truthy checks treated it as if the option was not provided,
causing requests to fall back to the browser default referrer behavior.
2026-06-09 09:41:19 -07:00
Angular Robot e6ae250802 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-08 15:40:04 -07:00
SkyZeroZx 47d68dcb26 fix(service-worker): Strips sensitive headers on cross-origin redirects
Removes `Authorization`, `Cookie`, and `Proxy-Authorization` headers when a request is redirected to a different origin. This aligns with the Fetch API's redirect algorithm to prevent sensitive information from being sent to third-party origins.
2026-06-08 14:49:29 -07:00
Kam a82f822057 docs: fix CurrencyPipe locale override example
The "Override current locale for CurrencyPipe" example used `{{ amount | currency: 'en-US' }}`, but the first `CurrencyPipe` argument is the currency code, not the locale, so `'en-US'` was treated as an invalid currency code (rendered literally as the symbol) and the locale was never overridden. Since `locale` is the fourth positional argument, the example now passes a valid currency code, display, and digits before it (`'USD' : 'symbol' : '1.2-2' : 'en-US'`), matching the parameter order shown on the CurrencyPipe API page.
2026-06-08 14:36:17 -07:00
KirtiRamchandani b7cb5844cf fix(docs-infra): avoid code copy button overlap
Reveal code copy controls on hover and focus so long code snippets stay readable while keyboard access and copy state feedback remain intact.
2026-06-08 14:19:49 -07:00
SkyZeroZx 3c70270c96 fix(compiler): sanitize two-way properties
Apply schema-derived sanitizer resolution to TwoWayProperty ops so native two-way DOM bindings emit the same sanitizer as one-way property bindings.

Add compiler compliance coverage for innerHTML, srcdoc, URL, resource URL, and security-sensitive attribute cases.
2026-06-08 13:12:22 -07:00
Bhuvansh855 422e6893e4 docs: fix malformed prettier-ignore comment in whitespace guide 2026-06-08 12:59:24 -07:00
aparziale dc8165e253 docs: close menù with click outside container
close menù with click outside container

Fixes #69222
2026-06-08 12:57:59 -07:00
Matthieu Riegler 9cfd3f52e1 docs: mention required behavior for booleans
fixes #68509
2026-06-08 12:54:40 -07:00
Aleksander Bodurri 06db706238 feat(devtools): improve transfer state tab
- promote to default-on (remove opt-in setting and gear-menu toggle)
- replace the <pre> value cell with a collapsible JSON tree
- add key filter and column sort (size sorts by raw bytes)
- show an educational empty state when the app has no transfer state
- iterate every root in the directive forest and merge their state
- guard size calculation against undefined and circular references
- register listener once with DestroyRef cleanup; add a loading timeout
- distinguish array/string badge colors via theme-aware tokens
- responsive value cell width; flex-based table scroll
- add a component spec; seed the harness fixture with more demo data
2026-06-08 12:47:13 -07:00
Georgi Serev fe50a7ea94 perf(devtools): optimize signal graph nodes value inspection
This change is based on the presumption that a signal graph can be significantly large memory-wise sometimes. This is the reason why we don't send the full graph to the FE but rather serialize its values and then lazy load them when they are needed, that is, during value inspection.
2026-06-08 12:34:03 -07:00
leonsenft b3748e9fe4 fix(core): correct container anchor collection order to match DOM layout
Historically, `collectNativeNodes` collected the container's anchor comment
node (`LContainer[NATIVE]`) before descending into the views contained inside
the `LContainer`. While this worked logically, it did not match the actual
physical layout of the DOM tree, where dynamic view content is inserted before
the container anchor. This discrepancy was particularly visible in projected
`@content` blocks where the anchor comment ended up rendered at the beginning
instead of the end of the content block.

This commit refactors `collectNativeNodes` to collect container nodes in the expected order:

1. Push the host element for dynamic containers where where `lContainer[NATIVE]
   !== lContainer[HOST]` (e.g., a `ViewContainerRef` injected on a `div` element).
2. Collect nodes in the container.
3. _Unconditionally_ push the container anchor comment.

Associated acceptance tests in `template_ref_spec.ts` are updated to match the
physically correct DOM order.
2026-06-08 12:13:12 -07:00
Matthieu Riegler 51724b48d2 ci: add myself to size-tracking
I feel confortable reviewing those
2026-06-08 11:52:20 -07:00
hawkgs a7d684517f refactor(devtools): use ng-filter for the router tree search
Use the reusable `ng-filter` for the router tree search.
2026-06-08 11:19:47 -07:00
Edu a816848373 ci: update devtools reviewers list
Update the Angular DevTools reviewers list in .pullapprove.yml. Add eduhmc and csmick, remove hybrist, and change milomg to approval-only.
2026-06-08 10:59:00 -07:00
SkyZeroZx c3207dc6b3 docs: add best practices for model and linkedSignal usage in components 2026-06-08 10:57:27 -07:00
leonsenft 11b206b919 fix(core): introduce disposal mechanism for Angular views in foreign @content
Coordinate template lifecycle events between Angular and foreign components to
allow clean teardown of nested Angular views inside a foreign container.

Previously, when Angular content was projected into a foreign component (for
instance, via render props), Angular had no way to receive destruction
notifications from the foreign component. If the foreign component unmounted
or conditionally removed its children, the nested Angular views remained active,
leading to memory leaks and incomplete lifecycle teardowns.

This change introduces the `ON_DESTROY` symbol and a new registration mechanism
(`ForeignOnDestroyFn`) on the `ForeignComponent` interface. The `foreignImport`
helper now takes an additional `onDestroy` callback function where the foreign
component can register to receive Angular's view-destruction callback.

During the creation phase, `ɵɵforeignContentFn` resolves the foreign component
from the constant pool using a new constant pool index and invokes the
`onDestroy` function. This registers a callback that destroys the corresponding
embedded view from the container.

In the compiler, `ForeignComponentOp` is modified to track the target constant
pool index, and `ForeignContentExpr` reification is updated to pass this index
to `ɵɵforeignContentFn`.
2026-06-08 10:17:40 -07:00
leonsenft 25c744c4d0 fix(compiler): support foreign components defined outside top-level scope
Currently, the template pipeline directly emits the raw expression for foreign
component definitions (such as `frameworkImport(MyComponent)`) directly into
the body of the generated template function. If a foreign component is defined
inside a local scope or is non-exported (e.g. nested inside a test block), the
emitted template function may not have access to that variable because
`ɵɵdefineComponent` and its template functions are emitted at the top-level
module scope. This previously caused reference errors during template
compilation.

This commit updates the compilation pipeline to instead ingest foreign
component references into the component's `consts` pool. The
`ɵɵforeignComponent` runtime instruction is updated to accept an index into the
constant pool rather than a raw expression. By routing the references through
the `consts` pool, block-scoped classes and variables are appropriately
captured by `ngtsc` without scoping errors, properly supporting nested/local
foreign component usage.
2026-06-08 10:17:40 -07:00
leonsenft b399f78c34 refactor(compiler): support passing @content blocks as functions
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.
2026-06-08 10:17:40 -07:00
Angular Robot 21e8ad37d9 build: update jasmine dependencies to v6
See associated pull request for more information.
2026-06-08 10:13:32 -07:00
SkyZeroZx 255151a413 fix(http): Rejects non-HTTP(S) URLs in JSONP requests
Prevents JSONP requests from using URLs with unsupported protocols
for improved security.

Fixes #68832
2026-06-05 15:09:37 -07:00
leonsenft 79e5d5d75f refactor(compiler-cli): validate @content block names for conflicts
Ensures `@content` blocks on foreign components have unique names and do not
conflict with static attributes or input property bindings.

Specifically, this commit introduces two new template diagnostics:
1. `CONFLICTING_CONTENT_DECLARATION` (8028): Raised when multiple `@content`
   blocks with the same name are defined under the same foreign component.
2. `CONFLICTING_CONTENT_AND_PROPERTY` (8029): Raised when a `@content` block's
   name matches an attribute or input property binding on the parent foreign
   component.

Both diagnostics include related information pointing to the location of the
conflicting declaration or property.
2026-06-05 12:46:32 -07:00
leonsenft 337442453b refactor(compiler-cli): disallow @content (children) in favor of implicit children
Defining a `@content (children)` block explicitly is unnecessary because
children should always be passed implicitly as direct nested content of the
foreign component. Using an explicit block could also lead to conflicts and
silent template rendering issues where implicit content (like whitespace)
accidentally overwrote the explicit block in the compiler's template
representation.

This change introduces a compilation error
(`FOREIGN_COMPONENT_CONTENT_UNNECESSARY_FOR_CHILDREN`) when an explicit
`@content (children)` block is detected, guiding developers to pass children
implicitly instead.
2026-06-05 12:46:32 -07:00
leonsenft 1f6e843648 refactor(compiler-cli): validate @content block placement
Adds validation to verify that `@content` blocks are only used as direct
children of foreign components.

Specifically:
- Defines a new compile diagnostic code `INVALID_CONTENT_PLACEMENT = 8026`.
- Updates `ForeignComponentFeatureAnalyzer` to traverse content blocks and
  report `INVALID_CONTENT_PLACEMENT` diagnostics if they are placed
  incorrectly.
- Removes the raw error thrown during ingestion in
  `packages/compiler/src/template/pipeline/src/ingest.ts`.
- Adds integration tests in `template_typecheck_spec.ts`.
2026-06-05 12:46:32 -07:00
leonsenft daa47b4aad refactor(compiler-cli): validate foreign component bindings during analysis
Refactors the unsupported bindings validation for foreign components from the
template semantics checker phase (during type-checking) to the component
analysis phase. Surfacing this check during component analysis means it will be
correctly reported during local compilation (which skips full template
type-checking).

Specifically:
- Creates a new helper `analyzeForeignComponentFeatures` in
  `foreign_component.ts` that traverses template elements and checks for
  unsupported outputs, references, and non-property inputs on foreign components.
- Removes the legacy validation from `template_semantics_checker.ts`.
- Invokes the validation during component analysis in
  `ComponentDecoratorHandler.analyze()`.
2026-06-05 12:46:32 -07:00
leonsenft 56607967db fix(core): introduce logical-only containers for foreign content
This commit introduces a logical-only container flag (`LContainerFlags.LogicalOnly`)
to support Angular features (like change detection and queries) on projected content
within foreign components, while relinquishing control over their placement in the DOM.

When content is projected into a foreign component via `ɵɵforeignContent`, the foreign
component receives the native DOM nodes directly and assumes control over their DOM
placement. Therefore, Angular must skip all platform-level view operations (insert,
move, delete) on these projected views.

To achieve this:
1. Introduce Logical-Only Containers:
   - Added `LContainerFlags.LogicalOnly` to represent view containers whose nodes are
     managed logically (by the consuming foreign component) rather than by the renderer.
   - Flagged `ɵɵforeignContent` containers with the `LogicalOnly` annotation.
   - Updated `applyContainer` in `node_manipulation.ts` to return early and skip platform
     DOM manipulations (insert, detach, destroy) on containers marked as logical-only.

2. Guard `collectNativeNodes`:
   - Updated `collectNativeNodes` in `collect_native_nodes.ts` to skip descending into
     logical-only containers. This prevents nested projected child elements (which are
     already claimed and placed inside nested foreign components) from being re-collected
     at the parent component's projection root level.

3. Unit and Acceptance Tests:
   - Added a comprehensive set of categorized acceptance tests in `foreign_component_spec.ts`
     covering nested foreign projections, projecting foreign components into Angular components,
     Signal-based view queries (`viewChildren`), event handlers, and change detection.
2026-06-05 12:46:32 -07:00
leonsenft f19bbe59dd refactor(compiler): support passing content to specific foreign component props
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.
```
2026-06-05 12:46:32 -07:00
leonsenft f89d0e4c8f refactor(compiler): support passing children to foreign components
Previously, any children nested inside a foreign component were ignored
during template ingestion. With this change, the compiler now:
1. Identifies when a foreign component has children in the template AST.
2. Compiles these children into a separate template view (using the
   standard TemplateOp).
3. Passes a `ɵɵforeignContent` expression under the `children` prop
   inside the foreign component's `props` object.

At runtime, the new `ɵɵforeignContent(index)` instruction instantiates the
template at the specified slot index in memory (detached from the DOM),
extracts its root DOM nodes, and returns them. These root nodes are then
passed directly to the foreign component's `props.children` so they can
be rendered by the foreign framework.

The instantiated children view is registered in the parent LView's
child tree, ensuring its change detection and destruction are managed
automatically as part of the standard Angular view tree lifecycle.
2026-06-05 12:46:32 -07:00
Alan Agius 5f36274da3 fix(common): use cryptographically secure SHA-256 for transfer cache key generation
Replace the custom 64-bit non-cryptographic combined DJB2 hashing implementation in HttpTransferCache with a robust, pure JavaScript, synchronous SHA-256 algorithm.
2026-06-05 11:18:12 -07:00
Angular Robot e0d9ea2560 build: lock file maintenance
See associated pull request for more information.
2026-06-05 11:14:14 -07:00
arturovt d3239a3ac2 refactor(core): convert LocaleDataIndex from enum to const object
TypeScript enums compile to self-executing function expressions that
are not tree-shakable, even when unused. Replace LocaleDataIndex with
a plain const object using `as const` to produce the same numeric
indices and literal types without the IIFE side-effect.
2026-06-05 11:10:42 -07:00
Georgi Serev 97be5f23fd feat(devtools): implement a signal graph nodes search
Implement singal graph nodes search for easier navigation within graphs with large sets of nodes. The search provides filtering by node type via `type:<SIGNAL_TYPE>` syntax.
2026-06-05 11:08:52 -07:00
Angular Robot 6899f1a1b2 build: update bazel dependencies to v3.2.1
See associated pull request for more information.
2026-06-05 11:01:30 -07:00
SkyZeroZx eeb03f4ea3 fix(common): Limits date format string length
Introduces a maximum length of 256 characters for date format strings.

This prevents potential Denial of Service (DoS) attacks by throwing an
`INVALID_DATE_FORMAT` error if an excessively long format string is
provided to `formatDate` or `DatePipe`, safeguarding against performance
degradation or application crashes.
2026-06-05 10:58:36 -07:00
Kam af7cb63151 docs: trim transparent padding from v22 event hero image
The v22 event hero PNG shipped with a wide transparent margin baked into
its 960x540 canvas. Under the shared `img { width: 100% }` rule that empty
border stretched along with the artwork, leaving visible space around the
image. Trims the canvas to the artwork bounds (831x473) so it renders
flush; the retained pixels are unchanged and the file shrinks from about
795 KB to 568 KB.
2026-06-05 10:56:26 -07:00
Angular Robot f759f273dd build: update all github actions
See associated pull request for more information.
2026-06-05 10:53:52 -07:00
Andrew Scott ed2420c0f8 fix(vscode-extension): inspect tsdk configurations correctly
Inspect both 'js/ts.tsdk.path' and 'typescript.tsdk' configurations separately, as the inspect method always returns a truthy object.

fixes #69145
2026-06-05 10:43:04 -07:00
marktechson 0197be381e docs: update landing page with embed link and updated messaging 2026-06-05 10:41:30 -07:00
Alan Agius 232f250a4c build(vscode-extension): disable make_latest on github release publication
Previously, when releasing the VS Code extension, the draft release
was created with make_latest: 'false', but the PATCH request that
published the draft release omitted this option. As a result, GitHub
automatically designated the published release as the 'latest' release.

This change explicitly passes make_latest: 'false' during the publish
request to prevent it from automatically becoming the latest release.
2026-06-05 10:31:54 -07:00
Angular Robot 240cb0d512 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-05 10:28:44 -07:00
Alan Agius cf9d7fa0f8 fix(platform-server): harden platform location origin validation during SSR (#69184)
Add allowOriginChange option to ResolveUrlOptions in resolveUrl to enforce same-origin validation on resolved URLs. When set to false, it prevents any cross-origin changes (including HTTP/HTTPS URLs), aligning the emulated server-side platform location environment with browser security behavior.

Refactor ServerPlatformLocation.replaceState to use allowOriginChange: false instead of manual comparison, hardening state change validation against cross-origin URLs.

Add unit tests in url_spec.ts and platform_location_spec.ts for the origin validation changes.

PR Close #69184
2026-06-05 17:20:43 +00:00
Alan Agius abfb04a342 refactor(platform-server): replace standard Error with RuntimeError (#69184)
Update platform-server to use Angular 's native `RuntimeError` class.
This aligns error throwing patterns in platform-server with other packages of the framework such as core, common, and platform-browser.

For URL and host errors, the error messages are configured to return only the raw dynamic URL when `ngDevMode` is false (in production) to aid in troubleshooting without bloating production bundles.

PR Close #69184
2026-06-05 17:20:43 +00:00
Kam 3960ad64e5 docs: bump schematics-for-libraries example peer deps to v22
The my-lib schematics-for-libraries example still declared `^21.0.0`
peerDependencies, the only adev example left on the previous major. Bumps
`@angular/common`/`@angular/core` to `^22.0.0`, matching the current major
and this file's stable-`^N.0.0` bump pattern.

Also adds this example's package.json to .prettierignore: it contains
`// #docregion` markers consumed by the schematics-for-libraries guide, and
Prettier's json-stringify parser (used for any package.json) rejects those as
invalid JSON. Editing the file surfaced this pre-existing incompatibility in
the format check.
2026-06-05 10:18:37 -07:00
Alan Agius af04e266cc refactor(http): deprecate jsonp support
JSONP is deprecated because it is prone to Cross-Site Scripting (XSS) attacks. Since JSONP works by executing arbitrary scripts in the global context, it bypasses modern Content Security Policies (CSP) and can lead to severe security vulnerabilities if the server or endpoint is compromised.

DEPRECATED: `HttpClient.jsonp`, `HttpClientJsonpModule`, and related JSONP classes/functions are deprecated. Use standard HTTP requests instead.
2026-06-04 15:28:19 -07:00
Doug Parker df77e42327 fix(forms): set additionalProperties: false on generated WebMCP form
This tells the agent that all input properties have been explicitly declared and that it should not attempt to specify additional arguments with unknown names. This provides a little more safety and gives the AI a little more information about the allowed set of inputs for this tool.
2026-06-04 14:18:06 -07:00
Matthieu Riegler cb8ceb1dde fix(http): ensure query parameters are inserted before URL fragments
Previously, when making an HTTP request where the URL contained a fragment (`#`) and `HttpParams` were provided, the parameters were appended to the very end of the URL (after the fragment). This resulted in the parameters being treated as part of the fragment rather than query parameters, potentially bypassing server-side logic and validation.
This commit updates the URL parsing logic in `HttpRequest` to split the URL by the fragment, correctly inserting the query string before any fragment.
2026-06-04 14:02:00 -07:00
Michael Small e100c75e37 docs: mention parse of validateHttp 2026-06-04 12:32:10 -07:00
Sreeved 82193a19ee docs: fix typo in update card link description 2026-06-04 12:29:03 -07:00
Stewart McGown 2d809e3170 test(core): add GC-based tests for signal graph prevConsumer leak fix (#68681)
Uses WeakRef + global.gc() to verify that destroyed effect consumers
become garbage-collectable when a non-live computed reads the same
producer.

The jasmine_test target is configured with node_options: --expose-gc.
GC tests are skipped in browser targets via isBrowser from
@angular/private/testing.

Made-with: Cursor

PR Close #68681
2026-06-04 19:25:36 +00:00
Stewart McGown 55639acd90 fix(core): prevent dangling prevConsumer reference from leaking destroyed views (#68681)
When `producerAccessed` creates a new link for a non-live consumer (e.g.
a computed signal with no readers), it eagerly sets `prevConsumer` to the
producer's current `consumersTail`. However, because the consumer is not
live, `producerAddLiveConsumer` is skipped and the link is never inserted
into the producer's consumer doubly-linked list.

This means the link holds a reference *into* the producer's consumer list
without being *part* of it. When the node that `prevConsumer` points to is
later removed via `producerRemoveLiveConsumerLink`, the dangling link is
not patched because it isn't traversable from the list.

The result is that the removed consumer link — and everything it
references — is kept alive by the dangling `prevConsumer` pointer on the
non-live link, which itself is kept alive through the computed signal's
`producers` linked list.

In practice this causes multi-MB memory leaks in Angular apps: a
root-provided service with a computed signal (e.g. `AttachmentApiService.urls`)
holds a producer link to `ApplicationEnvironmentService.environmentSignal`.
That link's `prevConsumer` captures a stale reference to a destroyed view's
`ReactiveLViewConsumer` link, retaining the entire LView hierarchy —
components, QueryLists, ElementRefs, and detached DOM — after the view is
destroyed.

The fix initializes `prevConsumer` to `undefined` at link creation time.
This is safe because `producerAddLiveConsumer` unconditionally sets
`link.prevConsumer = consumersTail` (line 513) when the link is actually
inserted into the consumer list. The value set in `producerAccessed` was
always overwritten for live consumers, and was never correct for non-live
consumers.

Made-with: Cursor

PR Close #68681
2026-06-04 19:25:36 +00:00
KirtiRamchandani bcb9f8da03 fix(docs-infra): reserve scrollbar gutter for mobile nav 2026-06-04 12:22:54 -07:00
Doug Parker e50d47a493 fix(core): disable WebMCP during SSR
In certain scenarios like `provideExperimentalWebMcpTools` in `app.config.ts`, a WebMCP tool may be declared before SSR has a chance to polyfill Domino and trigger an error due to an `undefined` `document` value. This aborts from the process before WebMCP has a chance to crash.
2026-06-04 11:44:28 -07:00
arturovt a786862c54 fix(core): use Object.hasOwn to handle null-prototype objects in toStylingKeyValueArray
Calling `.hasOwnProperty()` on an object created with `Object.create(null)`
throws a TypeError because such objects have no prototype and therefore no
inherited `hasOwnProperty` method. Replace it with `Object.hasOwn()`, which
is a static method immune to prototype chain issues.

Adds a regression test covering null-prototype objects passed to
`toStylingKeyValueArray`.
2026-06-04 11:37:43 -07:00
Matthieu Riegler ebb76a4313 docs: update support & release dates 2026-06-04 11:36:27 -07:00
Angular Robot 8da119857f build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-04 11:24:00 -07:00
Matthieu Riegler c5293c4c9d refactor(core): Also throw an error on iframe attributes set to undefined
This is more a hardening concern. Other non-nullish values were already throwing but here we make it explicit that undefined also throws.
2026-06-04 10:00:30 -07:00
Matthieu Riegler 6bde84fa8e fix(core): harden TransferState restoration against DOM clobbering
Reject non-script elements when reading the SSR transfer state payload by id.
This prevents attacker-controlled elements with a clobbered id from spoofing
hydration state.
2026-06-03 16:02:56 -07:00
Matthieu Riegler 7896e74222 refactor(devtools): Prevent cross-tab privilege escalation
The background script must not rely on the user-controllable `port.name` to authenticate DevTools panel connections.
2026-06-03 15:47:34 -07:00
cexbrayat 62859b9f69 docs: update reactive forms reference 2026-06-03 15:46:25 -07:00
bravesasha a28604be02 refactor(devtools): remove unnecessary async from serializeTransferState
Remove unnecessary `async`/`Promise<void>` from `serializeTransferState` and the
redundant `async () =>` wrapper in `provideAppInitializer` — the function contains
no async operations, so this is a zero behavior change cleanup.
2026-06-03 15:42:21 -07:00
Ben Hong c39b2a3b18 docs: fix directives guide issues and inaccuracies 2026-06-03 15:39:13 -07:00
Alan Agius d0dd9b6a6d build: deprecate @angular/animations and @angular/platform-browser-dynamic
Configure @angular/animations and @angular/platform-browser-dynamic as deprecated packages in the release configuration.
2026-06-03 12:30:34 -07:00
cexbrayat e8430032e1 fix(compiler-cli): bind switch exhaustive check expressions
Ensure switch exhaustive check parameters are visited during template binding so local template symbols are resolved correctly.

This allows:

```html
@let state = this.state();
@switch (state.mode) {
  @case ('show') { {{ state.menu }}; }
  @case ('hide') {}
  @default never(state);
}
```
2026-06-03 12:02:54 -07:00
Kristiyan Kostadinov 636cc94105 fix(compiler): more robust logic to check if regex can be optimized
Currently we only skip regex optimization if it has the `g` flag, however regexes can also have a state with the `y` flag.

These changes move to an allowlist model where we only optimize for a set of know flags.
2026-06-03 11:53:35 -07:00
SkyZeroZx 1ad6824d0d fix(common): skip transfer cache for uncacheable HTTP traffic (#69017)
Do not store HTTP transfer cache entries when either the request or response
uses `Cache-Control: no-store`, `Cache-Control: private`, or
`Cache-Control: no-cache`.

Also skip transfer cache when requests use the Fetch API `cache` option with
`no-store` or `no-cache`.

Because transfer cache serializes SSR HTTP responses into the rendered HTML,
Angular now treats these directives conservatively to avoid exposing sensitive
or explicitly uncacheable data through `TransferState`.

PR Close #69017
2026-06-03 18:47:44 +00:00
SkyZeroZx c0cbd46bd7 fix(http): skip transfer cache for fetch credentialed requests (#69017)
Treat HttpClient requests using `credentials: 'include'` and `same-origin` as credentialed
when deciding whether a response can be stored in the HTTP transfer cache.

The transfer cache already skips requests with `withCredentials`, `Cookie`,
`Authorization`, or `Proxy-Authorization` because those responses may contain
user-specific data. Fetch-backed requests can express the same credentialed
behavior through the `credentials` option, so these responses must not be
serialized into the SSR HTML.

This keeps credentialed SSR responses out of TransferState and aligns the
cache eligibility check with the fetch request options supported by HttpClient.

PR Close #69017
2026-06-03 18:47:44 +00:00
leonsenft 0c07356c5c fix(core): set current tnode in foreign component instruction on reuse
Previously, the `ɵɵforeignComponent` instruction set the `currentTNode`
state during the first template creation pass (via `getOrCreateTNode`),
but failed to do so on subsequent instantiations when the `TNode` was
accessed from cache.

This resulted in the global `currentTNode` state remaining unchanged from
the previous instruction. When closing a parent element (e.g., via
`ɵɵelementEnd`), this mismatched state caused assertion failures
because the framework attempted to close the wrong parent node.
This change fixes the issue by calling `setCurrentTNode(tNode, false)`
when the foreign component's `TNode` is retrieved from the cache.
2026-06-03 11:46:10 -07:00
leonsenft aeb55c8bc1 fix(compiler-cli): allow passing uninvoked signals as foreign component props
Avoid triggering the `interpolated_signal_not_invoked` diagnostic when
a signal is passed directly as a property binding to a foreign
component. Foreign components may accept signals directly, so they
should not be flagged as uninvoked in this context.

To support testing this, the typecheck testing infrastructure was
updated to allow defining mock foreign components in the test setup.
2026-06-03 11:46:10 -07:00
leonsenft e678955eac refactor(core): implement ɵɵforeignComponent instruction
Implement the `ɵɵforeignComponent` instruction to render foreign components
(components from other frameworks) inside Angular templates. The instruction
creates a host LContainer, instantiates a foreign view, executes the foreign
component's RENDER function, inserts the returned native DOM nodes, and
registers the disposal hook.

Add unit tests to verify element rendering, property passing, dependency
injection, and disposal on destruction.
2026-06-03 11:46:10 -07:00
leonsenft 330e209c69 refactor(core): add dev mode descriptions to foreign view boundaries
Add descriptive text to foreign view head and tail comments in dev mode to
assist in debugging.
2026-06-03 11:46:10 -07:00
Pawel Kozlowski 276bbaee8b docs: link to v22 blog post in changelog 2026-06-03 18:58:22 +02:00
Matthieu Riegler 752fb476eb refactor(devtools): Harden props navigation
To prevent any unwanted access/changes to some props like the `prototype` or `constructor`
2026-06-03 18:55:00 +02:00
Matthieu Riegler 66cbfee57b refactor(devtools): harden console invocations
We ensure that no prototype polution would affect console calls.
2026-06-03 18:52:31 +02:00
Andrew Scott b9e040f44d docs: release notes for the vscode extension 22.0.0 release 2026-06-03 18:26:51 +02:00
Alan Agius ba59de563f refactor(docs-infra): rename tutorial & example package.json.template to package.json
Rename the tutorial and example template packages' package.json.template files to package.json on disk.

To comply with ng_package limitations (which forbids floating package.json files in package output), we added a copy_file rule in the BUILD files to generate the .template files during build/packaging, and excluded the source package.json files from the filegroups. This keeps package.json as standard files in the source tree while preserving docs packaging and runtime logic.
2026-06-03 18:19:17 +02:00
cexbrayat c1b2c58525 docs: align dev skills examples with style guide 2026-06-03 18:11:45 +02:00
marktechson 20524958b7 docs: update landing page for v22 2026-06-03 17:54:49 +02:00
Pawel Kozlowski 595660d796 docs: update tutorials and playground to v22.0.0 2026-06-03 17:11:37 +02:00
Pawel Kozlowski 95ede172a6 docs: update version picker list for v22 release 2026-06-03 17:11:37 +02:00
Joey Perrott 09c03a2fe1 release: bump version of in memory web api 2026-06-03 16:36:28 +02:00
Alan Agius 27e8fc27cb release: bump Angular DevTools version to 1.15.1 2026-06-03 16:13:17 +02:00
Pawel Kozlowski 418b68a661 docs: release notes for the v22.0.0 release 2026-06-03 16:04:51 +02:00
Pawel Kozlowski 4b76e32988 docs: release notes for the v21.2.16 release 2026-06-03 14:32:19 +02:00
Cheng-Hsuan Tsai b84e5ef183 docs: add Signal Forms integration example to Angular Aria Autocomplete guide 2026-06-03 11:23:22 +02:00
Kam 192ac021e4 docs: use Türkiye as the country name in aria autocomplete examples
The aria autocomplete examples list "Turkey" in their country data, but
the country's official name is "Türkiye". Update all nine app.ts variants
to use it.

While there, remove a junk "Imporant" entry from the highlight/retro
variant's list, which is not a country and was a misspelled stray paste.
2026-06-03 11:19:53 +02:00
cexbrayat a6a3132903 docs: update DI fundamentals to use @Service 2026-06-03 11:18:50 +02:00
cexbrayat 3bb602ffe6 docs: simplify testing setup examples 2026-06-03 11:17:43 +02:00
Cheng-Hsuan Tsai af62d88bbd docs: update Aria Menu focus/hover style and add context menu example 2026-06-03 11:16:13 +02:00
cexbrayat ac30e4891a docs: update signal forms conditional rules 2026-06-03 11:06:03 +02:00
Matthieu Riegler e695379354 fix(core): harden inherit definition feature against polluted prototypes
Stop inheritance traversal before built-in prototype objects and only read `ɵcmp`/`ɵdir` when they are own properties of a super type. This prevents polluted inherited properties from being treated as Angular defs during inheritance merging.

Also adds regression tests covering polluted `Object.prototype.ɵdir` and `Object.prototype.ɵcmp` to ensure polluted host metadata is not inherited.
2026-06-02 13:25:55 +02:00
Pawel Kozlowski b08164121d docs: release notes for the v19.2.25 release 2026-06-02 13:21:37 +02:00
Pawel Kozlowski ebc7dbe477 docs: release notes for the v20.3.24 release 2026-06-02 13:11:46 +02:00
Angular Robot 30ff589566 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-06-02 12:25:05 +02:00
Cheng-Hsuan Tsai a76bc3c849 docs: add testing guides to Angular Aria 2026-06-02 11:25:00 +02:00
Michael Small 42391329c2 docs: fix min/max form template examples 2026-06-02 11:23:01 +02:00
Joey Perrott 3093edcad0 fix(docs-infra): secure update-assets script against RCE and SSRF
- Validate storedSha and storedBranch from _build-info.json.
- Validate latestSha returned from GitHub API.
- Validate branch in GithubClient.getShaForBranch and baseSha/headSha in GithubClient.getAffectedFiles.
- Use execFileSync instead of execSync to avoid shell execution.

TAG=agy
CONV=4e3e69ba-3f3d-416b-9ce4-9ef75486d2f3
2026-06-02 11:21:56 +02:00
Ben Hong c0eef66bbe docs: add conditional validation to signal forms validation guide 2026-06-02 11:20:52 +02:00
Pawel Kozlowski 3cc9e2b7a9 docs: release notes for the v22.0.0-rc.3 release 2026-06-01 22:08:04 +02:00
Alan Agius 0b19c92d44 fix(platform-server): throw on suspicious URLs and restrict protocol-relative URLs
Currently, the platform-server attempts to neutralize URL hijacking and SSRF
bypasses by collapsing multiple leading slashes in relative paths. However,
sophisticated bypasses using obfuscated protocols (e.g., carriage returns or
newlines) or relative-like backslash paths can still lead to unexpected
origin takeovers.

This commit improves security by doing the following:
- Rejects protocol-relative URLs by throwing an error if they are not
  explicitly permitted via `allowProtocolRelative`.
- Strictly validates resolved URLs against the provided origin using
  `isSafeOriginChange`. If a URL unexpectedly shifts origins, an error
  is thrown.
- Permits origin changes only when standard absolute http/https protocols are
  explicitly declared in the input URL.
2026-06-01 20:03:22 +02:00
Angular Robot 085e66ef03 build: update dependency @mcp-b/webmcp-types to v3
See associated pull request for more information.
2026-06-01 20:02:26 +02:00
Bhuvansh855 ac47524ede docs(core): fix typos and grammar in dependency injection guides 2026-06-01 18:56:09 +02:00
Matthieu Riegler 6038b9ede7 fix(migrations): Make the safe optional chaining idempotent
Our unit tests were missleading, the migration wasn't idempotent and `$safeNavigationMigration` were added multiple times on consecutive runs.
2026-06-01 18:50:21 +02:00
Matthieu Riegler 683172b39a refactor(core): Update webmcp support to use document.modelContext
The implementation in Chrome 150 moved `modelContext` from the navigator to the document (see webmachinelearning/webmcp/pull/184)

We're also removing the calls to the deprecated `unregisterTool` method.

fixes #68947
2026-06-01 18:49:04 +02:00
Angular Robot 688cb51d95 build: update dependency concurrently to v10
See associated pull request for more information.
2026-06-01 18:47:21 +02:00
Angular Robot 71a11b2f30 build: update pnpm to v11.5.0
See associated pull request for more information.
2026-06-01 18:45:37 +02:00
Matthieu Riegler ec4f08bb94 docs(docs-infra): simplify code block styles
#68940 introduced a regression that broke style for wrapped `code` blocks.
Simplifying the style by droping the unecessary gradient + before workaround fixes the issue.
2026-06-01 18:36:50 +02:00
Kam 032fae8b36 refactor(docs-infra): correct misspelled CodeHighlighter class name
The class exported from `code-highlighter.ts` was named `CodeHighligher` (missing the second `h`) and its private field was `cachedHighligher`, both disagreeing with the filename which spells "highlighter" correctly. Rename the class to `CodeHighlighter` and the field to `cachedHighlighter`, and update the sole consumer (`CodeBlock`). Pure rename, no behavior change.
2026-06-01 18:34:47 +02:00
KirtiRamchandani 9b5952e3a3 docs: mention Angular Aria in accessibility guide 2026-06-01 18:33:28 +02:00
Angular Robot 5215f7345a build: update dependency @mcp-b/webmcp-polyfill to v3
See associated pull request for more information.
2026-06-01 18:24:49 +02:00
Matthieu Riegler c743af4919 docs: add v22 entries to the update guide 2026-06-01 18:20:00 +02:00
Kristiyan Kostadinov f0b28f6443 fix(compiler): move projection attributes into constants
We can save some memory by moving the `attrs` passed into the `projection` instruction into the constant pool.
2026-06-01 12:28:28 +02:00
Kam f777dd112e docs: fix esbuild and TensorFlow branding on overview page
The esbuild card on the "What is Angular?" page rendered the bundler name three different ways (title "esbuild", link "ESBuild and Vite", body "Vite and ESBuild") so this unifies on the official lowercase "esbuild"; also corrects "Tensorflow" to "TensorFlow" to match the other brands on its line (Firebase, Material Design, Flutter, Google Cloud) which were already cased correctly.
2026-06-01 12:19:01 +02:00
arturovt 2b44a07ea7 docs: document //i18n(ph="name") placeholder syntax for template interpolations
The `//i18n(ph="name")` comment syntax for naming interpolation placeholders
in templates was not documented anywhere in the i18n guide, despite being a
supported compiler feature with test coverage.

Add a "Name the interpolation placeholder" subsection under "Mark text in
component template" in prepare.md, mirroring the existing subsection in
"Mark text in component code". Includes a cross-reference to the $localize
equivalent (`${var}:name:`) to help readers connect the two approaches.

Closes #52070
2026-06-01 12:18:03 +02:00
aparziale cbc36f59e0 docs: fix link debbuging and extended-diagnostics
Update link for 'Improve debbuging with better Angular error messages' and 'extended-diagnostics' sections

Fixed #69010
2026-06-01 12:16:57 +02:00
Kam 0010ad5910 fix(docs-infra): readable contrast for DEV/EXP api badges in light mode
The DEV (developer preview) and EXP (experimental) badges in the API reference list used `--page-background` for text, which is dark in dark mode (working as intended on the pale colored bg) but white in light mode, making the labels invisible against the near-white badge bg. Introduce an `--item-attr-text` CSS variable defaulting to `--page-background` and overridden to `--primary-contrast` in light mode, following the per-mode pattern the file already uses for `--item-attr-base-mix`.
2026-06-01 11:57:47 +02:00
Kristiyan Kostadinov 96ed0fe45b fix(docs-infra): round up media queries
Uses 1px increments for media queries, rather than the 0.01px we have now which seem to be a bit too precise and cause the UI to be stuck between states in some cases.

I've also removed some unnecessary `calc`, because the calculation is happening inside Sass already.

Fixes #69020.
2026-06-01 11:34:38 +02:00
cexbrayat 45e8fb5d6c refactor(forms): type built-in getError results
Add overloads for built-in validation error keys so callers get precise error payload types from getError.

This enables signal forms template patterns like:

```html
@if (login.getError('minLength'); as minLengthError) {
  <div>Login should be {{ minLengthError.minLength }} characters</div>
}
```
2026-05-29 14:58:40 +02:00
arturovt 0deac976f3 fix(core): use Object.create(null) for LOCALE_DATA as a hardening measure
Prior to this commit, `LOCALE_DATA` was initialized as a plain object literal:

```typescript
let LOCALE_DATA: {[localeId: string]: any} = {};
```

While `__proto__` is neutralized by the `replace(/_/g, '-')` sanitization step (becoming `--proto--`), keys like `constructor` and `prototype` pass through unchanged and would modify special properties on `Object.prototype` if used as bracket notation keys on a plain object.

**Example attack through the public API:**

```typescript
// attacker calls the public registerLocaleData API with a crafted localeId
registerLocaleData(data, 'constructor');

// internally becomes:
LOCALE_DATA['constructor'] = data;
// → modifies Object.prototype.constructor for every object in the process

// or with extraData:
registerLocaleData(data, 'constructor', extraData);
// LOCALE_DATA['constructor'][LocaleDataIndex.ExtraData] = extraData;
// → Object.prototype[LocaleDataIndex.ExtraData] = extraData
// → every plain object in the process now has this property
// → affects JSON serialization, property enumeration, and framework internals

// consequence — any subsequent object created in the process is affected:
const user = getUserFromSession();
console.log(user[LocaleDataIndex.ExtraData]); // → attacker-controlled value
```

In a long-running SSR server this pollution persists for the lifetime of the process and affects all subsequent requests from all users.

**The fix** initializes `LOCALE_DATA` with `Object.create(null)`:

```typescript
let LOCALE_DATA: {[localeId: string]: any} = Object.create(null);
```

A null-prototype object has no prototype chain, so any key is treated as a plain string with no special behavior, making prototype pollution impossible regardless of input — without relying on the sanitization step as the sole protection.
2026-05-29 14:55:47 +02:00
arturovt e50f504b2f fix(zone.js): validate __Zone_symbol_prefix to prevent DOM clobbering attacks
Previously, `__Zone_symbol_prefix` was read directly from `globalThis` without validating its type:

const symbolPrefix = global['__Zone_symbol_prefix'] || '__zone_symbol__';

This made it possible for DOM clobbering to interfere with Zone’s internal symbol handling. If an attacker injected a DOM element with the same name (for example via a form field or anchor ID), `global['__Zone_symbol_prefix']` could resolve to a DOM element instead of a string. Because DOM elements are truthy, the fallback would not be used, and Zone would construct invalid internal keys (e.g. “[object HTMLFormElement]...”), breaking patching and lookup logic in subtle ways.

This prevents DOM clobbering from influencing Zone’s internal symbol generation and keeps the patching system stable even in the presence of malicious or unexpected global values.
2026-05-29 14:54:13 +02:00
rootvector2 d109bf90d5 fix(common): only strip a literal /index.html suffix from URLs
Hit this while exercising `Location.normalize` with route paths that end in non-`.html` suffixes.

The unescaped `.` in the strip regex inside `_stripIndexHtml` matches any character, so e.g. `/foo/indexXhtml` and `/foo/index_html` both collapse to `/foo` before the base-path strip and end up resolving to the wrong route.

Escape the dot so only the literal `/index.html` suffix is stripped.
2026-05-29 13:16:01 +02:00
Alan Agius e14d34e9ee refactor(platform-server): clean up and simplify url resolution utility
Trims leading/trailing whitespaces in resolveUrl to normalize input.
2026-05-29 13:14:07 +02:00
Angular Robot 89c28d3704 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-29 12:21:16 +02:00
Christian Oliff 76dfb94e03 docs: changelog typo fixes 2026-05-29 11:56:26 +02:00
Christian Oliff 4640146f2d docs: changelog typo fixes
Found with cSpell VS Code extension
2026-05-29 11:56:26 +02:00
arturovt 2f49d5dba4 docs: document i18n object forms for sourceLocale and locales in angular.json
The `sourceLocale` and `locales` entries in `angular.json` accept object
forms (with `code`, `baseHref`, and `subPath`) that were never documented.

- Add an `i18n options` reference section to workspace-config.md covering
  the full shape of `sourceLocale` and each `locales` entry, including the
  distinction between `baseHref` (HTML only) and `subPath` (HTML + output
  directory name)
- Add `i18n` to the project configuration options table in workspace-config.md
- Expand the suboptions table in merge.md to mention the object forms and
  link to the new reference section

Closes #59664
2026-05-29 11:53:48 +02:00
Angular Robot 5f62a95bab build: update cross-repo angular dependencies
See associated pull request for more information.
2026-05-29 11:49:44 +02:00
Angular Robot 74d5886c46 build: update all non-major dependencies
See associated pull request for more information.
2026-05-29 11:47:46 +02:00
tjshiu f0e164e4cb docs: remove redundant keydown bindings in autocomplete examples 2026-05-29 11:46:35 +02:00
tjshiu 3939799e18 docs: add clear buttons inside autocomplete examples 2026-05-29 11:46:35 +02:00
Alex Rickabaugh 36ee538d3f docs: release notes for the v22.0.0-rc.2 release 2026-05-28 10:03:20 -07:00
Alex Rickabaugh 99c1eebcd5 docs: release notes for the v21.2.15 release 2026-05-28 09:53:57 -07:00
Pawel Kozlowski e2ccea9f45 docs: release notes for the v19.2.24 release 2026-05-28 16:45:57 +02:00
Pawel Kozlowski 25922d1755 docs: release notes for the v20.3.23 release 2026-05-28 16:29:09 +02:00
Angular Robot 80d6a3bcbb build: update bazel dependencies
See associated pull request for more information.
2026-05-28 16:17:44 +02:00
Angular Robot 4f79cfb2f5 build: update all github actions
See associated pull request for more information.
2026-05-28 16:09:16 +02:00
Kam 34d577f697 refactor(docs-infra): extract magic 27 in navigation-list tooltip threshold
The matTooltip on navigation list items was disabled when the label was
shorter than the literal `27`, repeated across four bindings in the
template. Lift the value to a protected readonly field so the threshold
has a name and lives in one place.
2026-05-28 16:08:08 +02:00
Alan Agius ec138c3645 fix(compiler): prevent namespaced SVG <style> elements from being stripped
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
2026-05-28 14:02:45 +02:00
Bhuvansh855 0e6cb4151c docs: fix grammar issues in resource guide 2026-05-28 13:48:01 +02:00
Angular Robot db59909c06 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-05-27 16:39:56 -07:00
Leon Senft 6981cd782a refactor(compiler): emit instructions for foreign components
When a template element matches an imported foreign component, the compiler
omits standard element instructions (`ɵɵelementStart`/`ɵɵelement`) and instead
generates a single `ɵɵforeignComponent` call. The call passes the exact foreign
import wrapper expression defined in `@Component.foreignImports` along with an
aggregated object literal containing all static attributes and property
bindings.
2026-05-27 16:39:00 -07:00
Cameron Smick 06d3758929 refactor(core): replace the type of the getDirectiveMetadata property of ExternalCoreGlobalUtils with the type of the getDirectiveMetadata property of FrameworkAgnosticGlobalUtils.
Modifying these types will allow Client-Only Wiz (and other frameworks) to implement ExternalCoreGlobalUtils & InternalCoreGlobalUtils instead of FrameworkAgnosticGlobalUtils, which includes additional properties they shouldn't implement.
2026-05-27 16:37:30 -07:00
Cameron Smick d069c55ab4 refactor(core): Split the ng global into internal and external objects
Split the `ng` global interface into two interfaces:
* `ExternalCoreGlobalUtils` includes all the functionality which has been shipped in a long-lived Angular version externally and which is subject to the versioning constraints described above.
* `InternalCoreGlobalUtils` includes internal-only functionality which has **not** been shipped in a long-lived Angular version.

This split means that all APIs in `InternalCoreGlobalUtils` can be iterated and evolved at a much faster pace. Angular DevTools can support those features, and we can make breaking changes more-or-less whenever we want. The downside is that external Angular developers cannot take advantage of those APIs or else we would be subject to the same versioning constraint we're trying to avoid here.

This means we can use `InternalCoreGlobalUtils` as a kind of "beta" channel for new DevTools APIs. Once that functionality is validated and the design is stabilized, the feature can be moved into `ExternalCoreGlobalUtils` and made available for external Angular developers when we're ready to commit to the long-lived version constraint. This will hopefully help us strike a better balance between iterating on new APIs quickly and maintaining stable APIs for external Angular users.
2026-05-27 16:37:30 -07:00
Matthieu Riegler 2acca1165d fix(http): Introduce a max buffer size for fetch requests on SSR
By default, the `FetchBackend` on SSR will limit the response body size to 10 MB.
If the response body exceeds this limit, an error will be thrown.

This default value can be configured by providing by setting the `maxResponseBodySize` in `provideServerRendering`.

This is to prevent DoS on the server when loading large files
2026-05-27 16:36:51 -07:00
Alex Rickabaugh a68a33e733 docs: release notes for the v20.3.22 release 2026-05-27 16:00:26 -07:00
Alex Rickabaugh 161c79d6cb docs: release notes for the v19.2.23 release 2026-05-27 15:50:15 -07:00
Yenya030 34090cb12e fix(http): exclude withCredentials requests from transfer cache
Update the transfer cache check to safely exclude all requests sent with the `withCredentials` flag.

By default, the HTTP transfer cache avoids caching user-specific responses to prevent sensitive data exposure or incorrect caching. While requests with explicit headers like `Cookie` or `Authorization` are excluded by default, requests can also be sent with credentials via the `withCredentials` flag without having those headers explicitly declared on the request object.

To keep user-specific responses from being cached, exclude `withCredentials` requests unconditionally, even when the `includeRequestsWithAuthHeaders` option is set to true.
2026-05-27 14:13:16 -07:00
Yenya030 ab459798d9 fix(http): skip TransferCache for cookie-bearing requests by default
Treat requests with a Cookie header like other auth-bearing requests and skip TransferCache caching them by default.

This preserves the explicit opt-in path via includeRequestsWithAuthHeaders, adds regression coverage for cookie-bearing requests, and updates the SSR guide to document the behavior.
2026-05-27 14:13:16 -07:00
Matthieu Riegler 6388675878 fix(http): prevent httpResource from leaking a subscription
Priori to this commit, in the case the subscription was emitting synchronous we were leaking the subscription. This commit fixes it.
2026-05-27 13:06:47 -07:00
Matthieu Riegler e0e902a8fa fix(core): prevent rxResource from leaking a subscription
Priori to this commit, in the case the subscription was emitting synchronous we were leaking the subscription. This commit fixes it.
2026-05-27 13:06:47 -07:00
RonGamzu 6f56202755 docs: fix typos in source code comments 2026-05-27 11:18:21 -07:00
Ricardo Chavarria 48b4625fb3 docs(docs-infra): add Spanish community translation
Add https://docs.angular.lat/ (Español) to the community translations section.
2026-05-27 11:16:53 -07:00
cexbrayat 842cf8f31b refactor(forms): mark date and limit signal forms APIs public
Promote the signal forms date validator and limit metadata APIs from experimental to public API.
2026-05-27 11:16:19 -07:00
Angular Robot b8e13872e0 build: update pnpm to v11.3.0
See associated pull request for more information.
2026-05-27 11:15:04 -07:00
Angular Robot bc9d033fe2 build: lock file maintenance
See associated pull request for more information.
2026-05-27 11:12:33 -07:00
tjshiu 30a8a2c4bd docs: modernize combobox and select guides and examples
Upgrades the guides and interactive examples to use modern signal-based APIs,
restoring the nested search dialogs and introducing datepicker grids.
2026-05-27 11:11:34 -07:00
Kam 8c3e46fb53 docs: fix preposition in libraries naming callout
The naming callout said the ng- prefix is "used from the Angular framework". Change to "used by", matching standard usage and the surrounding prose.
2026-05-27 11:09:40 -07:00
Harmeet Singh 741fcc4abf docs: clarify signals effect import source 2026-05-27 11:08:48 -07:00
Joey Perrott 983433d7f5 build: update dev-infra actions to 649c3afeaa46674507b9625537e49de54a695e2b
Updates the dev-infra action pin to the latest merge commit to resolve the retired Gemini model 404 failure.
2026-05-27 11:07:52 -07:00
Cameron Smick 23f3894c40 refactor(devtools): make the hydration property of DevToolsNode optional
Make the `hydration`` property of `DevToolsNode`` optional as frameworks like Client-Only Wiz don't have the same hydration concept as Angular and will not set one for nodes returned from `getComponentForest`.
2026-05-27 10:54:31 -07:00
Kristiyan Kostadinov abc61aaf7c fix(core): do not register dom triggers when defer blocks are in manual mode
Fixes that we were registering DOM triggers even if the `@defer` block is set up to be rendered manually. This matches the behavior we already have for timer triggers.

Fixes #68800.
2026-05-27 10:53:59 -07:00
Matthieu Riegler d7161fd431 fix(devtools): Add support for null-prototype objects
null-prototype don't inherite from the Object prototype and thus don't have constructors.

fixes #68798
2026-05-27 10:53:32 -07:00
Kam d808866f89 refactor(language-server): drop duplicate isAngularCore helpers in session
session.ts defined isAngularCore, isExternalAngularCore, and
isInternalAngularCore as byte-identical copies of the already-exported
versions in utils.ts. Only isAngularCore was used locally; the other
two were dead. handlers/template_info.ts already imports the utils
version. Remove the duplicates and import isAngularCore from utils.
2026-05-27 10:52:49 -07:00
Bhuvansh855 fdf0bf9a62 fix(docs-infra): improve inline code layout
Remove inline-block layout behavior from inline code elements
to improve wrapping and spacing in multiline documentation
paragraphs.
2026-05-27 10:52:14 -07:00
Joey Perrott a648e8e914 ci: configure setup and use pnpm in benchmark comparison workflow
The benchmark comparison workflow fails because it runs pnpm install
without setting up node and pnpm first. We configure the setup steps
manually so that checkouts from forks are supported.

Additionally, we update the benchmark comparison script (index.mts)
to use pnpm rather than hardcoded yarn commands to install
dependencies when checking out revisions.
2026-05-27 10:51:37 -07:00
Alan Agius 26f4ed5056 fix(dev-infra): draft GitHub release to support immutable releases
Update the release tool to create the GitHub release in a draft state initially and publish it only after the extension asset (.vsix) has been successfully uploaded.

GitHub shifted towards immutable releases. If a release is published instantly upon creation,the assets will not be able to be uploaded.
2026-05-27 10:50:20 -07:00
aparziale fcecf7016e docs: update CDK Overlay URL
Update CDK Overlay URL for strategy select.md and multiselect.md

Fixed #68914
2026-05-27 10:48:39 -07:00
Matthieu Riegler 7977a4b9bc docs(docs-infra): remove firebase studio launcher 2026-05-27 10:48:10 -07:00
Alan Agius e38db9b618 build: add explanation comment to confirmModulesPurge setting
Add a detailed comment to the `confirmModulesPurge: false` setting in
`pnpm-workspace.yaml`. This comment explains that this setting avoids
interactive prompts when `node_modules` needs to be purged and
recreated. This prevents package installation commands from hanging or
failing in non-interactive contexts (such as CI/CD pipelines, container
builds, or automated editor/agent environments) where stdin is
not a TTY.
2026-05-27 10:46:52 -07:00
Cheng-Hsuan Tsai 8f0ac6459e docs: update Angular Aria guides 2026-05-27 10:46:22 -07:00
Cheng-Hsuan Tsai cf2e6ec16d docs: modernize Aria guides 2026-05-27 10:45:49 -07:00
Andrew Scott fa7580061b fix(zone.js): avoid type error on custom object rejection with rejection property
Ensure that when a custom object with a 'rejection' property is thrown as a raw promise rejection, the unhandled promise rejection error logger does not crash with a TypeError while trying to access undefined zone properties.

Also wrap microtask queue draining and task frame counter updates with defensive try-finally blocks to guarantee internal scheduler states are properly reset under any potential call stack exception unwinding scenarios.
2026-05-27 10:45:13 -07:00
SkyZeroZx 31399c2171 fix(service-worker): Preserves HTTP cache mode in asset group requests
Ensures explicit HTTP cache mode from incoming requests is forwarded and maintained when creating fetch requests for assets, aligning with expected fetch behavior and preventing unintended cache handling.
2026-05-27 10:43:14 -07:00
SkyZeroZx 5b0e9663e5 fix(service-worker): Preserves explicit 'credentials: omit' in asset requests
Ensures that explicitly provided `credentials: 'omit'` options are preserved
when creating new requests, preventing unintended credential inclusion.
2026-05-27 10:43:14 -07:00
Alan Agius ce1c0f7ab9 fix(core): normalize tag names in runtime i18n attribute security context lookup (#68868)
Normalize namespaced tag names (e.g., :xhtml:a to a) inside i18nResolveSanitizer before looking up their security context. This ensures custom namespaced tag attributes undergo correct translation sanitization at runtime.

PR Close #68868
2026-05-27 10:40:22 -07:00
Alan Agius 4d79a52b2f fix(compiler): normalize tag names with custom namespaces in DomElementSchemaRegistry (#68868)
Custom XML/XHTML namespaced elements (e.g., <xhtml:a>) fall back to the standard HTML namespace during element creation at compile-time/runtime. However, their property and security context lookups inside the schema registry were incorrectly performed using the full namespaced tag name (e.g., :xhtml:a), which bypassed the default a|href sanitization registry and incorrectly returned SecurityContext.NONE instead of SecurityContext.URL.

This commit introduces tag name normalization inside DomElementSchemaRegistry for custom namespaces (other than the built-in svg and math namespaces). Custom namespaced tag names are now normalized to their simple HTML element counterparts for all registry queries, ensuring that correct property schema validation and dynamic security sanitization rules (such as URL sanitization) are enforced at runtime.

PR Close #68868
2026-05-27 10:40:22 -07:00
Alan Agius 75033d2001 fix(compiler): sanitize dynamic href and xlink:href bindings on SVG a elements (#68868)
Dynamic bindings to `href` and `xlink:href` attributes on SVG `<a>` elements (`<svg:a>`) were previously unmapped in the DOM security schema. As a result, they bypassed sanitization completely, creating a potential XSS vulnerability if bound to untrusted user inputs (e.g., `javascript:` URLs).

This fix mitigates this risk by:

1. Registering `href` and `xlink:href` on `<svg:a>` elements under the `SecurityContext.URL` context in both the compiler and core DOM security schemas.

2. Enabling template compilation to output runtime URL sanitization checks (`ɵɵsanitizeUrl`) on these attributes.

3. Adding regression and verification test cases to ensure dynamic SVG link bindings are safely sanitized at runtime while static values are correctly allowed.

PR Close #68868
2026-05-27 10:40:22 -07:00
Alan Agius 861d37e669 build: update minimum supported Node.js versions
Update the minimum supported Node.js versions for v22 and v24. Specifically, the minimum supported version for Node.js v22 is bumped to v22.22.3, and for v24 it is bumped to v24.15.0. This ensures compatibility with newer runtime versions and coordinates ranges across monorepo packages.
2026-05-27 10:39:17 -07:00
Matthieu Riegler e5f3b9def8 refactor(core): extend sanitization test coverage
This ensures that #68576 actually fixed a sanitization issue on uppercase elements/attributes
2026-05-27 10:38:11 -07:00
Matthieu Riegler 140c4d04cb fix(platform-server): prevent SSRF bypasses via backslash URLs in HttpClient
Encoding backslashes ensures that they are not normalized to slashes and where they could generate a protocol relative URL.
2026-05-27 10:23:29 -07:00
Alan Agius 1307ff355c fix(platform-server): secure location and document initialization against SSRF and path hijack
Normalizes the URL and path parsing logic inside platform-server by consolidating security checks and normalizations into a single, unified parseUrl helper function.

This includes:
- Collapsing multiple consecutive leading slashes and backslashes (e.g., // or /\) to a single forward slash to avoid protocol-relative parsing of path-like & relative inputs.
- Rejecting malformed absolute URLs that are otherwise accepted by lenient DOM parsers like Domino but rejected by standard WHATWG parsers, preventing SSRF / allowedHosts validation bypasses.
- Ensuring parseDocument gets the fully parsed and normalized URL instead of raw, unvalidated configuration values, preventing virtual document hostname adoption/origin hijack.
- Moving parseUrl unit tests into a dedicated url_spec.ts test file to keep platform_location_spec.ts clean and decoupled.
2026-05-27 10:22:36 -07:00
Matthieu Riegler b56e865148 fix(common): sanitize placeholder
The placeholder should be sanitized to prevent CSS/content injection.
2026-05-27 10:21:50 -07:00
Matthieu Riegler dfdfbe34a5 fix(common): add upper bounds for digitsInfo
The prevents the `roundNumber` function from allocating a large array.
2026-05-27 10:20:57 -07:00
Matthieu Riegler d5a489aed3 fix(core): sanitize meta selectors
Ensure that property/name are correctly escaped and doesn't break out of the intended selector.
2026-05-27 10:18:56 -07:00
Alex Rickabaugh 4f9ee3c056 refactor: add g3-only and 3p-only markers to replace specific g3 patches
Replace specific file patches applied during google3 sync with generic comment-based mechanisms.

By adding `// g3-only` prefix comments to g3-specific exports and declarations, and appending `// 3p-only` context to `@internal` tags, we enable generic tooling to handle these modifications during the sync process.

Additionally, wrap 3rd-party-only imports and exports (which should be stripped in google3) with `// 3p-only-start` and `// 3p-only-end` comment markers.

This reduces the need for maintaining custom file-specific patches in google3.

Also, add a comprehensive guide to these sync comment markers in `contributing-docs/google-markers.md` to assist external contributors.

Specifically:
- Add `// 3p-only` context to `@internal` in `directives.ts` for `foreignImports` and `deferredImports`.
- Add `// g3-only` commented exports in `core.ts`.
- Add `// g3-only-start`/`// g3-only-end` commented global declaration block in `zone.ts`.
- Wrap 3p-only imports in `fake_navigation.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Wrap 3p-only exports in `compiler-cli/index.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Add `// g3-only` and `// 3p-only` markers to `shared.ts` for `setDisabledStateDefault` configuration.
- Add `// g3-only` and `// 3p-only` markers to `feature_detection.ts` for semver dependency.
- Add `// g3-only` and `// 3p-only` markers to `domino_adapter.ts` for domino import path.
- Add `// 3p-only` marker to `ng_dev_mode` import in `event_dispatcher.ts`.
- Add `// g3-only` and `// 3p-only` markers to `MOUSE_SPECIAL_SUPPORT` in `event_contract_defines.ts`.
- Add `// g3-only` and `// 3p-only` markers to `BrowserModule` imports in `module.ts` (animations) and `browser.ts` (testing).
- Add `// 3p-only` marker to `goog.d.ts` reference tags in `util.ts` (platform-browser), `types.d.ts`, `ng_i18n_closure_mode.ts`, `tokens.ts`, and `global_utils.ts`.
- Wrap `Default` enum value of `ChangeDetectionStrategy` in `constants.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Add `// g3-only` and `// 3p-only` markers to `LEGACY_OPTIONAL_CHAINING_DEFAULT` in `legacy_optional_chaining_default.ts` and `legacyOptionalChaining` in `directive.ts`.
- Add `// g3-only` and `// 3p-only` markers to `DEFAULT_PARAMS_INHERITANCE_STRATEGY` in `router_state.ts`.
- Add `// g3-only` and `// 3p-only` (and block variants) markers to `@mcp-b/webmcp-types` imports in `declare_tool.ts`, `provide_tools.ts`, and `types.ts`.
- Add `contributing-docs/google-markers.md` guide.

TAG=agy
CONV=cd09a4f3-869a-4f41-949b-c91f1b8f1c51
2026-05-26 16:09:37 -07:00
Alex Rickabaugh 124ba10ead feat(core): add custom set option to linkedSignal
Introduce a custom `set` option in `linkedSignal` options to allow overriding and customizing the default write-back behavior of writable signals. This lets developers route updates back to the source of truth (e.g., converting Fahrenheit back to Celsius) or perform other side effects like updating properties inside a parent signal.

Additionally, the custom callback receives the standard signal setter as its second parameter (`rawSet`) to allow direct internal mutation if desired.

Fixes #59665

TAG=agy
CONV=addbb5c4-4233-49e8-b844-6f732d7d5c72
2026-05-26 16:01:35 -07:00
Alex Rickabaugh 06b004ec5c refactor(compiler): add support for compiling NgModules under isolatedDeclarations
This commit adds support for compiling NgModules in isolated declarations mode.
2026-05-22 14:00:18 -07:00
Andrew Scott df68a96b26 fix(vscode-extension): disable language server in untrusted workspaces
Restrict untrusted workspace support to limited mode. Skip launching the language client and registering commands in restricted mode, and only start them once workspace trust has been explicitly granted.
2026-05-22 12:22:07 -07:00
Andrew Scott d8c871ef80 refactor(vscode-extension): Remove effectively dead code
Since bundled path is at the start of probe locations, it's always going to be found first.
Workspace versions will never be used. getProbeLocations is effectively dead and confusing code.
2026-05-22 09:58:22 -07:00
Andrew Scott 3403e79f9f fix(vscode-extension): restrict jsdoc markdown trust and harden document opening
Restrict JSDoc hover links to the custom openJSDocLink command and implement document
opening using safe workspace APIs.
2026-05-22 09:56:25 -07:00
Andrew Scott 4f4820f410 fix(vscode-extension): prompt for confirmation before loading workspace tsdk
Harden the typescript.tsdk and js/ts.tsdk.path settings loading
in the VS Code extension client.

This change hardens tsdk loading by:
1. Ignoring workspace-level tsdk paths in untrusted workspaces.
2. Prompting the user for explicit confirmation before loading a
   workspace-level tsdk path in trusted workspaces, and saving the
   approval state in a secure, local workspaceState.
2026-05-22 09:52:14 -07:00
Angular Robot dfbe7a6ecd build: update github/codeql-action action to v4.35.5
See associated pull request for more information.
2026-05-21 13:21:30 -07:00
Angular Robot 23e744ec25 build: update all non-major dependencies
See associated pull request for more information.
2026-05-21 13:16:22 -07:00
arturovt 1563aae118 perf(forms): avoid redundant invalidations in parser errors signal
The `errors` linkedSignal in `createParser` had no equality check, so
every reset or recomputation — even to an identical empty array — would
mark downstream dependents as dirty and trigger unnecessary re-renders.

Add `shallowArrayEquals` as the equality function so the signal only
notifies dependents when the error list actually changes.
2026-05-21 10:57:50 -07:00
tjshiu f84653605a docs: modernize autocomplete examples and guide to signal apis 2026-05-21 08:54:04 -07:00
leonsenft fd6ef34ac9 docs: release notes for the v22.0.0-rc.1 release 2026-05-20 15:51:15 -07:00
leonsenft 16195d00bf docs: release notes for the v21.2.14 release 2026-05-20 15:36:37 -07:00
Kam 04f31cce3e docs: link to ng new reference from installation guide
The installation guide walks a developer through `ng new <project-name>` but provides no link to the `ng new` CLI reference, leaving every option the command supports undiscoverable from the install flow. Link `ng new` in the prose to the reference page so options are one click away.
2026-05-20 14:09:32 -07:00
arturovt 3b8503f960 docs: document FormBuilder.group() controlsConfig value shapes
The `@param` JSDoc for `FormBuilder.group()` previously described the argument only as “a collection of child controls”, without explaining the four supported value shapes:

* a raw value
* a `FormControlState`
* a `ControlConfig` tuple
* a pre-built `AbstractControl`

The fact that the second element of a `ControlConfig` tuple can accept `AbstractControlOptions` (for example to configure per-control `updateOn`) was especially non-obvious and undocumented.

This change adds a `@usageNotes` section with concrete examples covering each supported shape.

Closes #43984
2026-05-20 14:07:53 -07:00
Douglas Parker c7e08ebe59 docs: add WebMCP docs
Adds initial documentation of experimental WebMCP APIs.
2026-05-20 14:06:15 -07:00
tjshiu 069b0153aa docs: simplify multiselect examples by removing scroll resets 2026-05-20 14:04:12 -07:00
tjshiu 36500a70e3 docs: simplify multiselect overlay bindings and transitions
Remove the delayed overlayOpen signals and synchronization effects across all 9 multiselect example variations. Bind cdkConnectedOverlayOpen directly to popupExpanded() and remove conditional closing classes to simplify code.
2026-05-20 14:04:12 -07:00
tjshiu 8fa7311c6e docs: modernize multiselect guide and standalone examples
Update the multiselect guide and all 27 interactive examples to utilize
the modern standalone, Signal-based Angular ARIA APIs.

* Modernize all examples (Standard, Material, Retro)
  to use standalone directives, animations, and focus suppression.
* Update the multiselect guide API tables and templates:
  - Document ngComboboxPopup, cdkConnectedOverlay, and disabled input.
  - Document ngListbox selectionMode, focusMode, tabIndex, and value signal.
  - Document activeDescendant active focus tracking with ngComboboxWidget.
2026-05-20 14:04:12 -07:00
tjshiu 62f8449453 docs: modernize select guide and examples 2026-05-20 13:56:47 -07:00
Kam 41a772ec0b docs: fix grammar slips on pipes guide
Fixes subject-verb agreement in the overview opener and date/currency example, a singular pronoun for a plural antecedent under change detection, and an "a object" -> "an object" a/an slip.
2026-05-20 13:51:50 -07:00
arturovt d985957f09 docs: document barrel file caveat for @defer lazy chunks
Users often enable @defer expecting a separate lazy chunk but don't get
one, with no obvious error to explain why. The root cause is almost
always a barrel file import — the bundler treats the whole barrel as a
single module and can't split out individual exports.

Add a section to the defer guide that starts from the symptom (no lazy
chunk), shows the barrel import pattern that causes it, and gives the
direct-import fix.

Closes #52554
2026-05-20 13:47:42 -07:00
arturovt de9e3d136e docs: document content projection limitations
Add a Limitations section to the content projection guide covering two
common footguns that aren't obvious from the feature description alone.

First, projected content lives in the declaring component's view, not
the receiving component's. This means OnPush on the receiving component
doesn't prevent projected content from being checked on every parent
cycle, and projected content can't see the receiving component's
viewProviders.

Second, some library components (menus, tabs, lists) use ContentChildren
to wire up keyboard navigation and ARIA behavior and assume they own
their children directly. Projecting external content into them tends to
break that behavior silently.

Closes #49679
2026-05-20 13:31:45 -07:00
SkyZeroZx 1a11ae81b3 docs: remove outdated best practice regarding change detection strategy in components 2026-05-20 13:30:28 -07:00
arturovt ca44055166 docs: clarify ngDoCheck invocation behavior with OnPush strategy
The previous documentation for `DoCheck` / `ngDoCheck` implied that the
default change-detector had run on the directive itself, which is
misleading. `ngDoCheck` is actually invoked when the *parent's*
change-detector checks the directive's input bindings — meaning it fires
even for `OnPush` components whose own change detection was skipped.

Updated three places in lifecycle_hooks.ts:
- Interface description: scopes "the check" to input bindings in the
  parent template and adds an explicit OnPush callout.
- "detects changes" clarified to "detects changes to the directive's
  input bindings".
- Method description: "after the default change-detector runs" →
  "after the default change-detector has checked the directive's input
  bindings in the parent template".

Fixes #48140
2026-05-20 11:12:06 -07:00
Angular Robot 4104207913 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-20 11:09:39 -07:00
Angular Robot cb957238cb build: update bazel dependencies
See associated pull request for more information.
2026-05-20 10:44:19 -07:00
Kam 745ee71c25 fix(docs-infra): make absolute angular.dev hrefs relative in CLI option descriptions
CLI option descriptions are sourced from `@angular/cli` schema JSON
files, several of which contain absolute `https://angular.dev/...` URLs
in their `description` text. Those URLs render with the external-link
icon and push preview users out to production when viewed on
`next.angular.dev` or other dev previews. The path bypasses the existing
`link.mts` ban on absolute angular.dev links because option descriptions
go through `marked.parse` directly, without `AdevDocsRenderer`. Rewrite
the rendered hrefs whose values begin with `https://angular.dev/` (or
the `http:` variant) to root-relative paths so the resulting anchors
route through Angular's Router and resolve against the active
deployment. Subdomains such as `next.angular.dev/...` are intentionally
not rewritten because they refer to genuinely different deployments.

Closes #68795
2026-05-20 10:28:27 -07:00
Angular Robot 2953ca7b0d build: update pnpm to v11.1.3
See associated pull request for more information.
2026-05-20 10:19:39 -07:00
Angular Robot 6ff3256b90 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-05-20 10:11:57 -07:00
Alan Agius b70515cada docs: update supported Angular versions table to reflect v19 end-of-life status 2026-05-20 10:09:56 -07:00
arturovt 03161dc114 docs: clarify viewProviders visibility with projected content
The providers vs. viewProviders section explained what happens but not
why — specifically, why projected content can still access a parent
component's viewProviders. Added an explanation that DI follows where
content was declared, not where it's rendered, so projecting a component
into a child's ng-content cuts off the child's viewProviders but leaves
the declaring component's viewProviders reachable.

Closes #49202
2026-05-20 10:09:02 -07:00
leonsenft d89b707019 test(core): remove obsolete SVG script sanitization translation test
Removes the `should throw error on translated SVG script ResourceURL
attributes` integration test from `security_integration_spec.ts`.

This test is now obsolete because SVG `<script>` elements are stripped during
template compilation (implemented in 90494cd909). As a result, they are no
longer present in the compiled template to trigger runtime sanitization,
causing this test (which expected a sanitization error to be thrown) to fail.
2026-05-19 18:02:43 -07:00
leonsenft 933608c07f fix(core): synchronize core sanitization schema with compiler
https://github.com/angular/angular/pull/68689 recently updated the compiler
schema which should be kept in sync with the core schema. Fix applied by
running `pnpm bazel run //packages/core:dom_security_schema`.
2026-05-19 18:02:43 -07:00
tmpln 048817dfa7 fix(core): visit ICU expressions in signal migration schematics
Before this fix ICU expressions were not migrated.
2026-05-19 13:58:08 -07:00
leonsenft 7c60a98b3c fix(compiler-cli): support import aliases in foreignImports (#68674)
Correctly matches and resolves foreign components when imported under an alias
name inside the component file.

PR Close #68674
2026-05-19 13:42:10 -07:00
leonsenft d596d8bd0a refactor(compiler): support matching and validating foreign components in templates (#68674)
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
2026-05-19 13:42:10 -07:00
aparziale 8ebc900067 docs: update HTTP testing setup guidance
Update testing documentation clarify HttpClient testing providers

Fixed #68792
2026-05-19 13:41:13 -07:00
Angular Robot b53fa3cdaa build: lock file maintenance
See associated pull request for more information.
2026-05-19 13:22:40 -07:00
g.turri 4e55ceafc9 docs: Fix accepted Provider type in doc snippet
out of the box my IDE tells me there an error on

    const testProviders: Provider[] = [provideHttpClient(), provideHttpClientTesting()];

because `provideHttpClient()` returns an `EnvironmentProviders` so
I can't put it in a variable of type `Provider[]`
2026-05-19 13:19:33 -07:00
june-by c49661b57b docs(compiler): add typeCheckHostBindings option to angular compiler options 2026-05-19 13:09:25 -07:00
SkyZeroZx d251c0bf87 docs: Adds lazy service loading for best practice performance 2026-05-19 13:08:53 -07:00
Kam 96ba942a91 refactor(compiler): sync compiler_facade_interface replica with main
The replica at packages/core/src/compiler/compiler_facade_interface.ts drifted from the main copy. The file header specifies syncing via `cp main replica`; running it fixes field-order drift and relocates `legacyOptionalChaining?: boolean;` back onto R3DeclareDirectiveFacade (it was incorrectly on R3DeclareComponentFacade in the replica).
2026-05-19 13:07:05 -07:00
Georgi Serev 116b4cd936 fix(devtools): cluster-to-cluster relationships in signal graph
The PR addresses a missing step in the clustering phase of the signal graph processing on the DevTools frontend. Cluster-to-cluster relationship were missing from the graph, so the change fixes that.
2026-05-19 13:06:37 -07:00
Alan Agius 90494cd909 fix(compiler): strip namespaced SVG script elements during template compilation
Ensures that namespaced <script> elements (such as :svg:script) are correctly classified as PreparsedElementType.SCRIPT by the template preparser and stripped during compilation to prevent potential XSS vulnerabilities. Consequently, obsolete security schema mappings and runtime sanitization checks for <script> attributes have been removed since these elements are never present in compiled template outputs.
2026-05-19 13:06:00 -07:00
Cameron Smick dbceef6221 refactor(devtools): make the DevToolsNode element property optional
The Angular DevTools Extension doesn't use the `element` property in Client-Only Wiz apps. Once the new `ng.getComponentForest`` function is implemented, Client-Only Wiz could provide `ComponentTreeNode`s without an `element` property. This change supports that case by making the `element` property optional.
2026-05-19 13:04:49 -07:00
Cameron Smick 3c255bccc1 refactor(devtools): Modify buildDirectiveForest to set default values for properties that will not be included in the forest returned by non-Angular frameworks.
Set default values for the `directives`, `element`, `hydration`, and `component.isElement` properties of every `ComponentTreeNode` returned by `ng.getComponentForest` for non-Angular apps.
2026-05-19 13:04:15 -07:00
Cameron Smick 0cf8a61e58 refactor(devtools): add optional injector property to DevToolsNode and IndexedNode types
Add an optional injector property to the DevToolsNode and IndexedNode types. Features that require an injector use the injector stored on the node, if it exists, and fall back to getInjectorFromElementNode if it doesn't.
2026-05-19 13:04:15 -07:00
Cameron Smick 50c0ce8275 refactor(devtools): Modify buildDirectiveForest to call ng.getComponentForest if it exists.
A new ng global function, ng.getComponentForest, is being added to allow the framework to provide the component forest without writing metadata to the DOM. This will allow devtools to display components that don't render any DOM.
2026-05-19 13:04:15 -07:00
arturovt 8ec0d1eee8 fix(router): skip scroll-to-top on initial navigation when hydrating
When scrollPositionRestoration is enabled and the app hydrates an
SSR-rendered page, RouterScroller was unconditionally scrolling the
viewport to [0, 0] on the first imperative navigation. This discards
any scroll position the user established while the server-rendered
page was loading.

Fix by injecting IS_HYDRATION_DOM_REUSE_ENABLED into RouterScroller
and suppressing the scroll-to-top for the initial navigation only.
Subsequent navigations are unaffected.

Closes #64578
2026-05-19 13:01:53 -07:00
Alan Agius 61a97f22e8 fix(core): support prefix-insensitive DOM schema lookups and compile-time i18n attribute validation
Updates `DomElementSchemaRegistry` to strip `:svg:` and `:math:` namespace prefixes
from tag names before querying `SECURITY_SCHEMA` at compile-time. This allows SVG
and MathML attributes to correctly match their security contexts during compilation.
2026-05-19 13:00:32 -07:00
Andrew Scott ad37f52c12 fix(router): Add strict typing on 'getResolvedTitleForRoute'
The title property in Router type already requires that the return type of a resolved
title is a string. The type was looser here only because 'data' values are typed
as 'any'.

BREAKING CHANGE: The return type for `TitleStrategy.getResolvedTitleForRoute`
was previously 'any' while the actual return type could only be either `string`
or `undefined`. The return type now reflects the possible values correctly.
Code that reads the value may need to be adjusted.
2026-05-19 12:59:13 -07:00
Alan Agius 7390af78b1 test(upgrade): exclude unit test files from E2E application sources
Exclude `**/*.spec.ts` files from the `srcs` glob of the `full_sources` target.

Previously, `module.spec.ts` was compiled as part of the application's main sources because the glob pattern only excluded `**/*_spec.ts` (E2E specs). Consequently, `module.spec.js` was generated and included in the runfiles of the E2E test target, causing the Protractor runner to load and execute it. This failed since the E2E testing runner does not have access to unit testing imports like `@angular/core/testing`.
2026-05-19 12:57:48 -07:00
tmpln 16fe27bfef fix(core): do not insert todo when migrating void @Output
The following:

`@Output() someChange = new EventEmitter<void>();`

is correctly migrated to:

`readonly someChange = output<void>();`

However, a TODO is incorrectly inserted for subsequent emissions from
`someChange`, stating that an argument is expected.
2026-05-18 13:25:01 -07:00
Alan Agius 49ccb5154b build: update pnpm to v11.1.2
See associated pull request for more information.

Closes #68773 as a pr takeover
2026-05-18 13:24:31 -07:00
Kristiyan Kostadinov 9b7b9ba304 refactor(core): update internal utility
Updates the `getClosestComponentName` function to add support for a predicate function, based on internal requirements.
2026-05-18 13:23:46 -07:00
Angular Robot 7ec399ecb5 build: update dependency puppeteer to v25
See associated pull request for more information.
2026-05-18 13:23:09 -07:00
Matthieu Riegler 872853fbcb docs(docs-infra): Show function args
With this change non-overloaded functions also show the params + return type in a dedicated block.
2026-05-18 13:22:28 -07:00
Kam b7255f9d13 docs: open external anchors in adev markdown in a new tab
Several raw HTML `<a>` anchors in adev markdown link to external
sites without `target="_blank"`, so they open in the same tab
instead of a new one like the rest of the site's external links.
Add `target="_blank"` to match.
2026-05-18 13:18:20 -07:00
Alan Agius 0011664d1c fix(core): reject script element as a dynamic component host
To enhance application security and prevent accidental or malicious script execution, this change ensures that dynamically mounting a component via createComponent directly onto a <script> element throws a runtime error in development mode. SVG <script> elements are also rejected. The error message is designed to be fully tree-shakable under production builds where ngDevMode is disabled.
2026-05-18 13:16:31 -07:00
Kam 51b1db54ad refactor(core): remove deprecated UNSAFE_IFRAME_ATTRS alias
`UNSAFE_IFRAME_ATTRS` in the `RuntimeErrorCode` enum is a `@deprecated`
alias of `UNSAFE_ATTRIBUTE_BINDING` (same value -910) with no usages
anywhere. Drop it along with the paired
`tslint:disable-next-line:no-duplicate-enum-values` suppression.
`RuntimeErrorCode` is re-exported as `ɵRuntimeErrorCode`, so the
enum's value set is not a stability commitment.
2026-05-18 13:16:02 -07:00
Alan Agius cef4a095a2 refactor(core): align namespaced attribute validation and security schema contexts
Refactors the element security schema lookups and runtime attribute validation to
consistently account for SVG and MathML namespaces. This improves the modularity
and accuracy of security context mapping during template compilation and runtime
constant evaluation, eliminating redundant or false-positive lifecycle checks.
2026-05-18 13:09:39 -07:00
Leon Senft 88b0e420cf refactor(compiler): add support for importing foreign components
- Added the ForeignComponent interface in @angular/core.
- Added Component.foreignImports for importing ForeignComponents (supporting direct references and adapter function wrappers).
- Updated the compiler to handle ForeignComponent in template dependencies.
- Updated ngtsc to extract foreignImports from standalone components.
2026-05-18 13:08:59 -07:00
arturovt f43bad4d7b perf(forms): avoid spurious recomputation in FormField.parseErrors
`parseErrors` in `FormField` always produced a new array on every recomputation, even when nothing actually changed. The `?? []` fallback created a new empty array whenever `parseErrorsSource` was undefined, and `.map()` also returned new object references each time.

Since computed signals use reference equality by default, those new arrays were treated as changed values. That caused unnecessary updates to propagate through `validationState.parseErrors` and the combined errors chain, triggering extra recomputations during change detection.

Fix this by adding `{equal: shallowArrayEquals}` to the `parseErrors` computed, matching the existing `errors` computed and the validation computeds in `field/validation.ts`.

This prevents empty arrays from triggering updates while still correctly propagating real parse-error changes.
2026-05-18 13:08:33 -07:00
SkyZeroZx 00c284015c fix(core): makes resource URL sanitizer lookup case-insensitive
Ensures the resource map for URL sanitization is queried using lowercase tag and property names, improving robustness by handling case variations consistently.
2026-05-18 13:07:34 -07:00
cexbrayat 9a7dedced6 docs: use when in signal forms rule examples
Update the Signal Forms guides to match df54e6a7b2, which introduced the consistent {when: ...} form for these rules.
2026-05-15 12:16:50 -07:00
Angular Robot 2959d6bd9e docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-15 11:41:49 -07:00
Angular Robot 991e0b4276 build: update dependency node to v22.22.3
See associated pull request for more information.
2026-05-15 11:39:51 -07:00
Angular Robot 2864fed214 build: update all non-major dependencies
See associated pull request for more information.
2026-05-15 11:38:00 -07:00
Douglas Parker 1963a0eb18 refactor(forms): add provideExperimentalWebMcpForms
This enables the use of the `experimentalWebMcpTool` option on signal forms and implicitly declares a WebMCP tool based on the form data model. This is an experiment inspirted by the WebMCP declarative forms API to see if Angular's framework-level knowledge of the form's declarative data model can produce higher quality WebMCP tools than the web standard can on its own with less effort from the developer.

Example:

```typescript
// main.ts

import {bootstrapApplication} from '@angular/platform-browser';
import {provideExperimentalWebMcpForms} from '@angular/forms';
import {MyComp} from './form';

bootstrapApplication(MyComp, {
  providers: [
    // Activate the feature.
    provideExperimentalWebMcpForms(),
  ],
});
```

```typescript
// form.ts

import {Component, signal} from '@angular/core';
import {form} from '@angular/forms';

@Component({ /* ... */ })
export class MyComp {
  private readonly f = form(signal({
    firstName: '',
    lastName: '',
  }), {
    // Implicitly creates a WebMCP tool named `createUser` which accepts a `firstName` and `lastName` as parameters.
    experimentalWebMcpTool: {
      name: 'createUser',
      description: 'Creates a user with the given name.',
    },

    // Invokes the submit action when the agent calls the WebMCP tool.
    submission: {
      action: () => {
        console.log('User clicked submit, or agent called the tool!');
      },
    },
  });

  // ...
}
```
2026-05-15 11:35:22 -07:00
Jens Kuehlers 358d2e63fb docs: move Angular 19 to unsupported versions 2026-05-15 10:41:39 -07:00
Angular Robot 1a7f00f7c0 build: update cross-repo angular dependencies to v22.0.0-rc.0
See associated pull request for more information.
2026-05-15 10:40:32 -07:00
Andrew Scott 13911b156b refactor(compiler-cli): Remove unused properties of IndexedComponent interface
These properties aren't used in the Kythe indexer and can be removed
2026-05-15 10:37:57 -07:00
Alex Rickabaugh 0a9b19454d refactor(core): add internal API for creating foreign views
Introduces `createForeignView`, an internal API for creating foreign view
directly inside `LContainer`s. Foreign views (`TViewType.Foreign`) are bounded
by head and tail comment nodes and can contain dynamic, non-Angular DOM nodes.

Updates Render3 node manipulation to support inserting, detaching, and moving
foreign views along with their internal content.
2026-05-15 10:33:52 -07:00
Matthew Beck 71f8d488e0 docs: release notes for the v22.0.0-rc.0 release 2026-05-13 16:34:51 -07:00
Matthew Beck 21ca0918c7 docs: release notes for the v21.2.13 release 2026-05-13 16:26:24 -07:00
Kam 7557b339ea refactor(core): mark resource() overloads as @publicApi 22.0
#68253 graduated `resource`, `rxResource`, and `httpResource` to stable
by swapping `@experimental` for `@publicApi 22.0` across three files.
The two `resource()` overloads in `packages/core/src/resource/resource.ts`
were missed and still carried `@experimental 19.0`. The public-api
golden already lists both overloads as `// @public`, so this aligns the
source with what the rest of the codebase reflects.
2026-05-13 15:54:55 -07:00
Alan Agius dbf38537f2 docs: add version 22 to the browser support reference table 2026-05-13 15:33:56 -07:00
AleksanderBodurri ec63947dc6 refactor(core): patch special provider classes with __NG_ELEMENT_ID__
Calls a new patchSpecialProvider function to attach __NG_ELEMENT_ID__ and track special providers for debug tooling
2026-05-13 12:15:21 -07:00
Kristiyan Kostadinov 06f6dec7aa fix(compiler): type check invalid for loops
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).
2026-05-13 11:26:42 -07:00
Ben Hong 3584eeb491 docs: add clarification around plain object models
Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-05-13 11:24:34 -07:00
Angular Robot a8421d37de build: update devinfra digest to eaa9aaa
See associated pull request for more information.
2026-05-13 11:22:49 -07:00
Alan Agius 739bd37b0a release: bump Angular DevTools version to 1.15.0 2026-05-13 15:28:49 +02:00
Angular Robot 642fd43ea6 build: update pnpm to v11.1.1
See associated pull request for more information.
2026-05-12 21:39:31 -07:00
Angular Robot f247ea417a build: update cross-repo angular dependencies
See associated pull request for more information.
2026-05-12 21:38:32 -07:00
Matthieu Riegler f05d675651 build: update cross-repo angular dependencies (main)
This PR also replaces the implementation of the select component on ADEV due to the aria breaking changes
2026-05-12 16:41:38 -07:00
Angular Robot ff816fb5ae build: update cross-repo angular dependencies
See associated pull request for more information.
2026-05-12 16:41:38 -07:00
Angular Robot d42fdf151e docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-12 15:50:42 -07:00
Matthew Beck 7ff4847e03 Revert "refactor(compiler-cli): drop @ts-ignore around fs.readFileSync"
This reverts commit e0593ecc8b.
2026-05-12 15:20:55 -07:00
Matthew Beck 1bb2c68200 docs: release notes for the v19.2.22 release 2026-05-12 14:48:31 -07:00
Joey Perrott 6a07fddb9a build: update @angular/ng-dev
Update @angular/ng-dev to use commit 2c36222db3f44751284cc93b3806dbe1baee583a to pull in the latest merge validation logic fixes.
2026-05-12 14:26:10 -07:00
Matthew Beck 1d3bf59f9a fix(compiler): simplify handling of colon host with a selector list
Update `_convertColonHost` to extract and use only the first argument from a `:host(...)` selector list, ignoring subsequent arguments instead of splitting and duplicating the selector list. Also remove the obsolete test cases from `host_and_host_context_spec.ts`.
2026-05-12 14:25:46 -07:00
Matthew Beck 6de4955124 fix(compiler): remove dedicated support for legacy shadow DOM selectors
Remove `_shadowDOMSelectorsRe` and `_convertShadowDOMSelectors` from `shadow_css.ts` so that `::shadow`, `::content`, `/shadow-deep/`, and `/shadow/` are no longer treated specially or stripped from user CSS. Instead, they are naturally scoped like standard selectors. Also remove the legacy failing test from `shadow_css_spec.ts`.
2026-05-12 14:24:29 -07:00
Matthew Beck 23f0898edb fix(compiler): remove deprecated shadow CSS encapsulation polyfills
Completely remove support for `polyfill-next-selector`, `polyfill-unscoped-rule`, and `polyfill-rule` from `shadow_css.ts`, along with their associated methods and regular expressions. Also delete `polyfills_spec.ts` entirely.
2026-05-12 14:24:02 -07:00
Matthew Beck 770e505f78 fix(compiler): preserve leading commas in animation definitions
Update the regular expression in `_scopeAnimationRule` to prevent absorbing and deleting leading commas after `animation:`. Also remove the corresponding legacy test case from `keyframes_spec.ts`.
2026-05-12 14:22:56 -07:00
Matthew Beck 338bf7d46f fix(compiler): enforce parentheses containing arguments for :host-context
Modify `_colonHostContextRe` and `_hostContextPattern` to strictly process `:host-context` only when parentheses containing at least one non-whitespace argument character are present. Update `_colonHostRe` to explicitly NOT match `:host` when followed by a hyphen. When invoked without parentheses or with empty parentheses, the selector is completely ignored and treated as a standard CSS pseudo-class in the source text. Also update the legacy test case from `host_and_host_context_spec.ts`.
2026-05-12 14:22:19 -07:00
Kam e0593ecc8b refactor(compiler-cli): drop @ts-ignore around fs.readFileSync
The `readFileBuffer` method in `node_js_file_system.ts` was wrapped in
`@ts-ignore` to suppress a TS2322 Buffer/Uint8Array typing error that
was fixed in the TypeScript 5.9.2 upgrade. The minimum supported
TypeScript is now 6.0, so the suppression is dead.
2026-05-12 13:21:53 -07:00
Joey Perrott cdef73a249 build: update @angular/ng-dev
Update the @angular/ng-dev dependency to the latest build to pull in recent fixes and improvements.
2026-05-12 12:08:55 -07:00
Angular Robot 66b9259401 build: lock file maintenance
See associated pull request for more information.
2026-05-12 11:42:31 -07:00
Aleksander Bodurri 84d757446b refactor(devtools): use WeakRef in idToInjector map for injector cleanup
Replace the manual injectorsSeen cleanup mechanism with WeakRef and FinalizationRegistry. The old approach worked but coupled cleanup to the UI change detection and required tracking seen injectors across traversal. WeakRef lets the browser handle this naturally, removing the injectorsSeen set and the manual cleanup loop.
2026-05-12 11:37:07 -07:00
SkyZeroZx a617967d90 refactor(http): update HTTP resource options APIs to stable
Marks `HttpResourceRequest`, `HttpResourceOptions`, and `HttpResourceRef` as public APIs following the stabilization of the Resource API in https://github.com/angular/angular/pull/68253
2026-05-12 10:48:03 -07:00
Paul Gschwendtner 95034a7b92 ci: mark devversion as unavailable
Currently OOO and I don't want reviews to be necessarily stuck for too long.
2026-05-12 10:47:09 -07:00
Alan Agius e90423f5f7 build: disable strict release age checks in pnpm workspaces
Updates all pnpm-workspace.yaml configurations across the repository to set minimumReleaseAgeStrict: false. This resolves dependency installation failures caused by missing time field metadata in the npm registry for certain packages such as @babel/helper-globals. A TODO comment is also added to each configuration file to track future investigation of this registry metadata issue.
2026-05-12 10:43:00 -07:00
Matthew Beck 62710ad4d6 docs: release notes for the v20.3.21 release 2026-05-12 10:13:01 -07:00
Alan Agius 62f8dbb626 build: remove @angular-devkit/build-angular dependency and configure pnpm resolution mode
Try to fix pnpm 11 and defer integration test.
2026-05-12 08:49:44 -07:00
Angular Robot 7acac39ada build: update pnpm to v11.1.0
See associated pull request for more information.

Closes #68687 as a pr takeover
2026-05-12 08:49:44 -07:00
Andrew Scott 1f287b9ba7 refactor(router): Move target RouterState creation before 'blocking' stage
This change moves `RouterState` creation to _before_ the `afterPreactivation` step,
which is the step that pauses until bootstrap listeners are complete. It is used for
'enabled blocking' initial navigation and destructive hydration. After this stage,
activation is expected to be (more or less) synchronous.

More importantly than above (since enabled blocking and destructive hydration are
essentially deprecated), this also oves the state creation before the view transition
creation.

These are done to accomodate features in the future that would depend on the RouterState
(e.g. ones which need to know which `ActivatedRoute` instances are new and which are reused).
These features may include additional async blocks/waits, which should not happen after view
transition creation (which freezes the UI until resolved).
2026-05-11 18:29:52 -07:00
Kam e661f4d255 refactor(compiler-cli): replace forEach with for...of in entry_point
Convert four `.forEach()` calls in `private_export_checker.ts` and
`reference_graph.ts` to `for...of`, matching the iteration style used
elsewhere in the compiler. The TODOs that forced these workarounds are
obsolete.
2026-05-11 18:29:04 -07:00
Angular Robot 2f143bf9c9 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-11 12:46:59 -07:00
Angular Robot 90c4223aa9 build: update pnpm to v11
See associated pull request for more information.
2026-05-11 12:43:55 -07:00
Douglas Parker 38e26f0759 refactor(core): add "experimental" to WebMCP API names.
WebMCP is still an experimental standard and going through frequent changes in the Chrome implementation and the standards process. As a result, we should be clear about the support status of this API and its overall stability guarantees.
2026-05-11 12:43:06 -07:00
Kam 7a146238ba refactor(compiler-cli): drop @ts-ignore around jsDocParsingMode
The getters and setters for jsDocParsingMode in `host.ts` and
`ts_create_program_driver.ts` were suppressed with @ts-ignore to
support TypeScript 5.2, which lacked the property on `ts.CompilerHost`.
The minimum supported TypeScript is now 6.0, and `jsDocParsingMode`
is part of the public TypeScript API, so the suppressions can go.
2026-05-11 12:40:25 -07:00
Matthieu Riegler 52a848790f docs: update guides to use @Service
In the cases where it was preferable to use `@Service` in place of `@Injectable`
2026-05-11 12:38:23 -07:00
Jessica Janiuk 43a8df9520 ci: update pullapprove
This removes thePunderWoman from active review requests, but leaves passive on.
2026-05-11 12:37:45 -07:00
Ben Hong ef134ac367 docs: add new signal forms field metadata guide
Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-05-11 12:05:27 -07:00
Matthieu Riegler 7360c1da68 docs(docs-infra): improve api docs extraction
This allows us to show the API docs when the jsdoc block is at the top of a overloaded function (and not on the implementation signature).

eg: `injectAsync`
2026-05-11 12:03:39 -07:00
Kam 4ec076e13c docs: add inject() example to "Forwarding injected dependencies"
Lead the section with the recommended `inject()` pattern (child
inherits the property, no `super` forwarding), and keep the existing
constructor DI example after as the alternative. Also fixes a typo
where the verb "class" should read "pass".
2026-05-11 12:02:45 -07:00
Kam 0629e7e505 docs: recommend output() over EventEmitter in reactive forms guide
The "Save form data" step pointed at `EventEmitter` while the rest of
the guide uses modern APIs (e.g. `inject(FormBuilder)`). Swap to
`output()` and align the TODO in the profile-editor example.
2026-05-11 12:02:03 -07:00
SkyZeroZx 538d0a8e93 docs: remove experimental warnings from resource/signal forms documentation 2026-05-11 11:46:08 -07:00
arturovt 7623580378 fix(platform-server): forward BEFORE_APP_SERIALIZED errors to ErrorHandler
Errors thrown by BEFORE_APP_SERIALIZED callbacks were previously logged
via console.warn and silently ignored. This meant failures such as
TransferState.toJson() encountering a circular reference would go
unreported in apps that use a custom ErrorHandler (e.g. Sentry).

Errors are now forwarded to the application's ErrorHandler, making them
visible through whatever reporting mechanism the app has configured.
The render continues to completion after the error is reported.

Closes #65811
2026-05-08 15:10:09 -06:00
Kam 8b46492b7e docs: fix two 404 links in the roadmap
"Introduce built-in control flow" => guide/templates/control-flow (was
the now-removed next.angular.dev/essentials/conditionals-and-loops),
and "Improve documentation and schematics for standalone components"
=> essentials/components (was the bare `components`, not an adev route).
2026-05-08 15:05:40 -06:00
Angular Robot 80632a9f97 build: update dependency bazel to v8.7.0
See associated pull request for more information.
2026-05-08 09:58:39 -06:00
Alan Agius b3de3af0dd docs: remove note regarding lack of support for ng test --debug in browser mode
This is no longer the case.

Closes #68621
2026-05-08 09:57:08 -06:00
Matthew Beck 38b2bede60 docs: release notes for the v22.0.0-next.12 release 2026-05-08 09:24:20 -06:00
Kristiyan Kostadinov c72ebcb1ad fix(core): allow service with factory on abstract classes
Fixes that setting a `@Service` with a `factory` on an abstract class was resulting in a compilation error.
2026-05-08 10:16:15 +02:00
Michael Small 89ee8a8162 docs: fix signal forms async validator typings
docs: add response types for form async `onSuccess`

docs: set defined fallback for async validator params

docs: replace `this.` w/`const`

docs: give fallback string for form async validators

docs: replace `onError` overwritten by `onSuccess`

docs: use `undefined!` for now w/async validators

chore: lint form's `async-operations.md`
2026-05-07 18:17:57 -06:00
SkyZeroZx a0b998e293 docs(docs-infra): use signals & improve types
Use signals to avoid markForCheck.

Simplify takeUntilDestroyed usage by relying on implicit DestroyRef.

Improve type safety by typing inject(ElementRef).
2026-05-07 18:17:29 -06:00
SkyZeroZx 307723a352 docs: add documentation for de-duplicate host directives 2026-05-07 17:53:42 -06:00
Matthieu Riegler a7dab601fa refactor(core): use the @Service decorator where possible.
A few bytes to win.
Added only on the services that don't rely on constructor DI.
2026-05-07 17:03:30 -06:00
Michael Small 7b4791f474 docs: add FormField/FormRoot imports + move comment w/backticks 2026-05-07 16:56:45 -06:00
Michael Small 44c0293a3e docs: fix applyWhenValue form example 2026-05-07 16:54:06 -06:00
Michael Small 0ef43c5ff3 docs: rename outdated validateTree example's model 2026-05-07 16:53:41 -06:00
Angular Robot 28e7bfaf77 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-07 16:51:57 -06:00
Andrew Scott 932a163cb6 refactor(compiler-cli): fix path normalization and trailing comments (#68454)
Ensure paths are normalized before comparison and key generation in tcb_adapter.ts to avoid failures on Windows.
Ensure a newline before appending imports in TypeCheckFile.render to prevent trailing comments from neutralizing them.

PR Close #68454
2026-05-07 15:42:33 -07:00
Andrew Scott 4f9c824dd9 feat(language-service): Typecheck templates which would require inline typecheck blocks (#68454)
This change updates the language service to generate TCBs for templates that would previously
have required inlining. The new strategy is to copy the original source and then do inlining
in the external TCB. This allows language features and type-checking in templates of non-exported
classes (such as test components) or classes with local, non exported dependencies.

PR Close #68454
2026-05-07 15:42:33 -07:00
Andrew Scott 7f0265e43a feat(language-service): compile non-exported classes if standalone (#68454)
Langauge service previously never compiled non-exported classes. This avoided issues
where test modules would cause diagnostic noise due to components appearing in
declarations of two modules, for example. This change updates the logic to ensure
non-exported, but standalone classes _are_ still compiled.

fixes #65515

PR Close #68454
2026-05-07 15:42:32 -07:00
Angular Robot 3ac11a5e02 build: update pnpm to v10.33.4
See associated pull request for more information.
2026-05-07 16:40:35 -06:00
Angular Robot 827781ea12 build: update all non-major dependencies
See associated pull request for more information.
2026-05-07 16:39:49 -06:00
Angular Robot 17d8be4a76 build: update bazel dependencies
See associated pull request for more information.
2026-05-07 16:37:18 -06:00
Alan Agius 60552a73e8 fix(platform-server): add allowedHosts option to renderModule and renderApplication
In server-side rendering (SSR) setups, passing request URLs directly to the lower-level rendering APIs `renderModule` or `renderApplication` can expose applications to Server-Side Request Forgery (SSRF) or Host Header Injection attacks via absolute-form request URLs.
To mitigate these vulnerabilities at the framework layer, this commit introduces the `allowedHosts` option to `PlatformConfig` (supporting exact hostnames, wildcards like `*.example.com`, or `*` to allow all).

During platform initialization inside `createServerPlatform`, the hostname of the request `url` is validated against the `allowedHosts` list. If the hostname is not authorized, bootstrap immediately throws a host validation error, preventing unauthorized rendering and silent SSRF bypasses.

Closes #68436
2026-05-07 16:30:03 -06:00
Angular Robot 3bf1b10bcf build: update all github actions
See associated pull request for more information.
2026-05-07 16:28:57 -06:00
Kristiyan Kostadinov 1f238ab567 fix(docs-infra): switch remaining adev services to @Service
Reworks all the remaining injectables in adev to use `@Service`.
2026-05-07 16:23:26 -06:00
Matthew Beck b1699da827 test: remove invalid css that was causing issues with the postcss parser
These tests happened to use garbage "{c}" declaration lists which caused
the parser to choke. Given that we already have tests demonstrating
similar behavior and that's not what these tests were meant to
demonstrate, I've updated them to use empty declaration lists.
2026-05-07 16:20:16 -06:00
Alan Agius 5b421c61cd fix(core): disallow event attribute bindings in host bindings unconditionally
Moves the event attribute validation check outside of `ngDevMode` in the `elementAttributeInternal` instruction to ensure that bindings to event attributes like `on*` are always blocked at runtime.
2026-05-07 16:19:22 -06:00
Andrew Scott bc655d006f refactor(compiler): Update indexer API to be generic
Rather than requiring TS AST in the indexer API, this update makes it generic with adapters to provide necessary information. This allows other analysis pipelines that don't use TS AST to work with the indexer.
2026-05-07 16:16:59 -06:00
Kam ed333c3992 docs: normalize product name casing across docs
Several user-facing docs, tooltips, and tutorial code samples used
non-canonical spellings of product names. This normalizes them to
the form each project uses for its own brand.
2026-05-07 16:09:44 -06:00
Alan Agius d8e5514f30 docs: update Node.js version requirements in version reference table 2026-05-07 16:06:38 -06:00
Bhuvansh855 dc4b3172df docs(animations): improve grammar and clarity across animation guides 2026-05-07 16:03:41 -06:00
SUMIDA, Ippei 2fcfffbc7d docs: Update error display for password field in signal forms playground
Change error message display from paragraph to list format in signal forms playground.
2026-05-07 15:53:07 -06:00
Alan Agius f1738b5032 fix(migrations): remove compiler import from safe optional chaining migration
Removes the @angular/compiler import from the safe optional chaining migration. This import is not needed as the compiler package import is side-effectful and has no functional use here.
2026-05-07 15:44:08 -06:00
Alex Rickabaugh e3dc87cbd8 release: cut the zone.js-0.16.2 release 2026-05-06 16:44:48 -07:00
Alex Rickabaugh 853a91e928 docs: release notes for the v22.0.0-next.11 release 2026-05-06 16:31:53 -07:00
Alex Rickabaugh b2c08dfead release: bump the next branch to v22.1.0-next.0 2026-05-06 16:31:53 -07:00
Alex Rickabaugh 8b3973aaad docs: release notes for the v21.2.12 release 2026-05-06 15:49:14 -07:00
Alex Rickabaugh a02ac76866 docs: release notes for the v20.3.20 release 2026-05-06 15:30:20 -07:00
Douglas Parker 3b0ae5fef0 feat(core): add provideWebMcpTools
This is an ergonomic wrapper around `declareWebMcpTool`, allowing a user to define multiple tools directly on an injector's providers, rather than needing to find an injection context.

Example:

```typescript
import {bootstrapApplication, provideWebMcpTools} from '@angular/core';

await bootstrapApplication(RootComp, {
  providers: [
    provideWebMcpTools([
      {
        name: 'hello',
        description: 'Says hello',
        inputSchema: {type: 'object', properties: {}},
        execute: async () => ({content: [{type: 'text', text: 'Hello, World!'}]});
      },
    ]),
  ],
});
```

The `execute` function is invoked in the injection context of the `Injector` it is provided to, meaning you can easily `inject` dependencies and invoke them.

This also works particularly well with route `providers` and `withExperimentalAutoCleanupInjectors`, registering the tools when the router is navigated to and then automatically unregistering them when navigating away. Note that `withExperimentalAutoCleanupInjectors` is required for unregistration to work.

```typescript
import {provideWebMcpTools} from '@angular/core';
import {provideRouter} from '@angular/router';

provideRouter(
  [
    {
      path: '',
      component: Home,
      providers: [
        provideWebMcpTools([
          {
            name: 'hello',
            description: 'Says hello',
            inputSchema: {type: 'object', properties: {}},
            execute: async () => ({content: [{type: 'text', text: 'Hello, World!'}]}),
          },
        ]),
      ],
    },
  ],
  withExperimentalAutoCleanupInjectors(),
);
```
2026-05-06 14:13:20 -07:00
Douglas Parker 77ec83782f refactor(core): run declareWebMcpTool callback in an injection context
This uses the injection context the tool is registered in for the `execute` callback and makes it a little more ergonomic to inject and use services in this context.
2026-05-06 14:13:20 -07:00
Douglas Parker ef1810197b feat(core): export experimental declareWebMcpTool support
This exports `declareWebMcpTool`, a mechanism for registering WebMCP tools and tying them to Angular's `Injector` lifecycle. This function immediately registers the given tool and automatically unregisters it once the associated `Injector` is destroyed.

This exports the function and all transitively reachable types *except* for JSON Schema types as there are quite a lot and we don't want to couple to this particular implementation will likely be obsoleted by built-in types as the standard develops. If users want to leverage those, they should add their own dependency on `@mcp-b/webmcp-types`.
2026-05-06 14:13:20 -07:00
Douglas Parker b2c0c91f8f refactor(core): implement declareWebMcpTool
This is a relatively light wrapper around `navigator.modelContext.registerTool` which ties tool registration to the lifecycle of an `Injector`. When the `Injector` is destroyed, the tool is automatically unregistered. This makes it easier to create WebMCP tools without having to worry about managing unregistration.

I went a little off-spec by providing the `AbortSignal` to the `execute` function. I suspect something like this will be added eventually and there are some early discussions of that, but AFAICT, this behavior is not defined yet so I'm making something up instead so the `execute` function can observe a cancellation based on the `Injector` being destroyed.

This uses `@mcp-b/webmcp-polyfill` for testing, as it provides a small `modelContextTesting` utility for listing and invoking WebMCP tools. Unfortunately it is slightly out of date of the current Chrome spec (it requires `modelContext.unregisterTool` to be called, whereas the spec recently removed this option and expects you to provide an `AbortSignal` to `registerTool`). My slightly hacky solution for the moment is to both trigger the `AbortSignal` and also call `unregisterTool` safely. In production, only the `AbortSignal` happens, but in testing the `unregisterTool` code path is used. Hopefully this will get smoothed out as the spec matures and `@mcp-b/webmcp-polyfill` updates over time.
2026-05-06 14:13:20 -07:00
Douglas Parker 5387e13b10 refactor(core): vendor @mcp-b/webmcp-types
This copies WebMCP types into `@angular/core` and redistributes them. Ideally this would just be a regular dependency, but we need to do this vendoring for API extractor to properly process the types, since they will inform `@angular/core` public API.

One downside of this approach is that the dependency is not visible in Intellisense, breaking type inference.
2026-05-06 14:13:20 -07:00
kirjs 043055f6de refactor(forms): support when consistently for maxDate and minDate validators
This commit updates maxDate and minDate to consistently check and apply the 'when' option for conditional validation.
2026-05-06 14:10:12 -07:00
kirjs f9e2b8d902 refactor(forms): update API golden files for signal forms overloads
Regenerated public API golden files after adding overloads for hidden, disabled, and readonly.
2026-05-06 14:10:12 -07:00
kirjs 0806b2f02b refactor(forms): use overloads and JSDoc for deprecations
This commit removes runtime console warnings and uses TypeScript overloads with JSDoc @deprecated annotations to handle backward compatibility for conditional rules.
2026-05-06 14:10:12 -07:00
kirjs 3f3b85ca44 refactor(forms): regenerate API golden files for signal forms
Regenerated public API golden files after updating rules and validators to use 'when' parameter.
2026-05-06 14:10:12 -07:00
kirjs 7d9862f0be refactor(forms): support deprecated signatures for backward compatibility
This commit restores support for passing functions directly to hidden, disabled, and readonly rules, marking them as deprecated.
2026-05-06 14:10:12 -07:00
kirjs df54e6a7b2 refactor(forms): use when consistently for conditional rules and validators
This commit updates the signal forms API to use a consistent 'when' parameter for conditional rules and validators, replacing direct function arguments.
2026-05-06 14:10:12 -07:00
Alex Rickabaugh 7745365910 feat(forms): graduate signal forms APIs to public API
Replaced `@experimental` tags with `@publicApi 22.0` across all Signal Forms APIs under `packages/forms/signals` to mark them as ready for general use in v22.

TAG=agy
CONV=0af6c644-225a-4212-a49a-5843d17ec638
2026-05-06 12:01:41 -07:00
Leon Senft 1f30aacbe5 refactor(forms): bind formatted date string to min/max for minDate/maxDate (#68001)
* Test that `minDate`/`maxDate` binds to `min`/`max` on date and time inputs
* Test that `min`/`max` attribute can be set directly on date and time inputs
* Relax type checker to allow `min`/`max` bindings on date and time inputs

PR Close #68001
2026-05-06 11:59:18 -07:00
Leon Senft 276c917b34 refactor(forms): add validation rules for date constraints (#68001)
- Added `minDate()` and `maxDate()` for validating constraints on `Date` inputs.
- `ReadonlyFieldState.min` and `.max` now return
  `Signal<NonNullable<TValue>`. This ensures that `min` and `max` inputs
  on custom controls can accept a reliable type (matching their value
  type).
- Made the `TWrite` type parameter of `MetadataKey` contravariant to
  properly indicate that it's writable.
- Added `LimitKey` as a convenience type for defining validation limit
  metadata (e.g. `MAX_NUMBER`, `MIN_DATE`).
- Added `LimitSelectionKey` which can be used to bind a `LimitKey` with
  value-specific aggregation logic, to a generic metadata key (e.g. use
  `MAX_NUMBER` to aggregate numbers for `MAX`).

PR Close #68001
2026-05-06 11:59:18 -07:00
Leon Senft 592a12d6c9 refactor(forms): remove string support from min and max validation rules (#68001)
The `min` and `max` validation rules previously handled `string` values
to accommodate numbers bound to text inputs. However, this is no longer
necessary as the control binding itself handles the conversion.

This change removes string support from these rules, simplifying the
types to `number | null`. The validation logic has been updated to use
concrete checks (`value === null || Number.isNaN(value)`) to ensure safe
TypeScript narrowing.

Associated tests have been updated to:
- Remove string-specific validation checks.
- Add coverage for text input bindings.
- Add coverage for empty input handling (standard behavior where empty
  sets model to null and skips validation).

BREAKING CHANGE: `min` and `max` validation rules no longer support
string values. Bound values must be numbers or null.

PR Close #68001
2026-05-06 11:59:18 -07:00
Alex Rickabaugh 849dba6c65 fix(forms): implement custom control reset propagation
Introduce a highly decoupled FVC and CVA custom control reset mechanism, and implement the framework-wide automatic `transformedValue` and native controls clearing bridge for both new Signal Forms and legacy forms (Template-driven and Reactive).

1. Custom Control Reset Propagation (Bug #2):
- Establish agnostic custom control resetting via `FormFieldBindingOptions.reset` in `FormField`.
- Ensure that `FieldNode.reset()` unconditionally triggers `writeValue` updates on CVA custom controls.
- Protect against duplicate writes during subsequent change detection updates in `control_cva.ts` by verifying and tracking previous written values in the local bindings cache.

2. Unified Framework-wide FormControl Integration:
- Introduce a monorepo-wide private InjectionToken `ɵFORM_CONTROL_INTEGRATION` and `ɵFormControlIntegration` interface to act as the single, decoupled bridge for hooking up FVC parse errors and receiving control resets across both Signal and legacy forms architectures.
- Simplify Signal Forms: make `FormField` implements `ɵFormControlIntegration` directly, removing the intermediate context object and reducing DI boilerplate down to a clean `useExisting: FormField` provider. Triggers the `onReset` callback directly inside `FormField.reset()`.
- Upgrade Legacy Forms: `NG_CONTROL_INTEGRATION_PROVIDER` provides the renamed token. `NgControl` handles the event subscription internally (`set onReset(callback)`) to recursively listen to `control.events` (`FormResetEvent`) lazily only when assigned, resolving all `FormControl` swapping timing and lifecycle cleanup races automatically.

3. Automatic `transformedValue` and Native Controls Utility Clearing:
- Make `Parser.reset()` method required in the interface for a cleaner and non-defensive execution.
- Wire `transformedValue` into the new integration token `ɵFORM_CONTROL_INTEGRATION` to clear validation parsing states on resets.
- Lazily resets the UI-facing `rawValue` linked signal utilizing the original native `linkedSignal.set` callback (`originalSet`), correctly bypassing the UI-to-model parser loopback and preventing redundant model writes during `reset()`.
- Wire up Native Controls (`control_native.ts\Device`): Hook `parent.onReset` inside native element creation to automatically trigger the native `parser.reset()` and force DOM writes (`setNativeControlValue`) back down to the DOM input value during resets, ensuring native elements with pending parsing validation errors are successfully cleared and synced on form resets.

TAG=agy
CONV=8b4cee1e-2117-42a4-b242-c8ec7bf01752
2026-05-06 10:45:40 -07:00
Suraj Yadav 68c3abbe09 fix(forms): synchronize controls with the model on reset
Synchronize `controlValue` with the model `value` following `reset()`. This
ensures the UI will reflect the form model in cases where a control had a
pending change–delayed by debouncing–at the time it was reset.
2026-05-06 10:45:40 -07:00
Matthieu Riegler 5a7c1e62dc feat(core): add ability to cache resources for SSR
This commit adds a `transferCacheKey` option to enable easy caching for `resource`/ `rxResource`.
2026-05-06 09:57:49 -07:00
Alan Agius b8d3f36ed9 feat(compiler-cli): add support for Node.js 26.0.0
Updates the supported Node.js engine versions to include Node.js 26.

This allows running the CLI on Node.js 26.0.0 and above while continuing to support active LTS versions.
2026-05-06 09:55:38 -07:00
Angular Robot 188b0d5b5a build: update cross-repo angular dependencies
See associated pull request for more information.
2026-05-05 17:08:42 -07:00
hawkgs 1cb2e6bf5b feat(devtools): improve value highlighting in object previews
Introduce a more fine-grained value preview highlighting based on the property type in the `ng-object-tree-explorer`.
2026-05-05 17:06:41 -07:00
hawkgs f8045272b5 refactor(devtools): update object value previews
Improve BigInt, function and object/class instance value previews during state serialization.
2026-05-05 17:06:41 -07:00
Matthieu Riegler bd30caaf45 refactor(language-service): add quick info for $safeNavigationMigration
`$safeNavigationMigration` is a magic function, we need to provide a quick info for it.
2026-05-05 17:03:55 -07:00
Sam Severance 2e0ca49f32 docs: clarify @for track expression scope to include properties and methods 2026-05-05 17:02:52 -07:00
Matthieu Riegler 3524de29f3 fix(forms): Add support for range type with outside of native bounds
range inputs don't allow value that are outside their min/max ranges.

fixes #68480
2026-05-05 16:26:03 -07:00
Jaime Burgos f81fa6e691 docs: add documentation for lazy loading services and update navigation 2026-05-05 15:57:36 -07:00
Matthieu Riegler d7b475122a refactor(core): promote resource & rxResource to stable
The time has come.

Note: #67382 introduced a breaking change where you could notice some sublte timing change on how `value` is set when using `rxResource` or a `stream` on a `resource`
2026-05-05 15:55:25 -07:00
Alex Rickabaugh 5835a5e3a7 fix(forms): prevent orphan field crashes in debounceSync and async validation
- Short-circuit `FieldNode.debounceSync()` if the node is orphaned right
  before calling `this.sync()`, preventing unhandled promise rejections
  on dead state reads.
- Include `this.node.structure.isOrphaned()` in `shouldSkipValidation`
  computed signal in `ValidationState`. This safely shields the entire
  validation layer (sync and async errors) from executing on dead nodes during
  in-flight async validator resolutions.
- Append robust reproduction specs to `orphan_repro.spec.ts` for both the
  `debounceSync` and `validateAsync` async race conditions. Include an intentional
  promise resolution workaround for an experimental Angular `core/resource`
  `PendingTasks` leak deadlock bug uncovered during testing.

TAG=agy
CONV=054e0185-f5f0-40e3-9c9b-413309f36cf6
2026-05-05 15:54:42 -07:00
Alex Rickabaugh 3c44d7c90b fix(forms): fix orphan field error on blur during array removal
Explain the race condition: when an item is deleted from a model array, its
DOM element is removed during change detection, which fires a `blur` event
synchronously. The `blur` handler tries to mark the field as touched,
navigating up to `keyInParent` which throws because the item is already gone
from the array in signals state.

Fix by introducing an `isOrphaned` check that short-circuits `markAsTouched`
early, backed by a reactivity-insulated `childrenMap` poll to avoid double
scans and prevent unhandled exceptions.

TAG=agy
CONV=054e0185-f5f0-40e3-9c9b-413309f36cf6

Fixes #66711

Co-Authored-By: Matthieu Riegler <kyro38@gmail.com>
2026-05-05 15:54:42 -07:00
Kam 8a7f955f0f docs: correct "Angular JS" to "AngularJS"
"AngularJS" is the official product name for the v1.x line and is
written as a single word. A few places in the docs and package
READMEs used "Angular JS" with a space. This normalizes those
references to the canonical spelling.
2026-05-05 12:42:39 -07:00
Leon Senft 708631f2c4 fix(forms): prohibit concurrent submits in signal forms
Prohibit concurrent submits in signal forms to prevent duplicate actions and side effects when a submission is already in progress.

If `submit()` is called while a prior submit is in progress for the same field or any of its parents, it returns `false` immediately without running the action again.

This commit also updates the documentation in `form-submission.md` to reflect this behavior.

Fixes #68317
2026-05-05 11:14:03 -07:00
Angular Robot fc526331e3 build: lock file maintenance
See associated pull request for more information.
2026-05-05 09:35:19 -07:00
hawkgs 93b5496ee8 refactor(devtools): minor improvements of the resolution path UI
Change the string representation of `InjectionToken`s; Add an explanatory label to the visualization.
2026-05-05 09:34:57 -07:00
Kristiyan Kostadinov b225a5d902 fix(compiler): invalid type checking code if field name needs to be quoted
Fixes that we were producing invalid TypeScript if an input with an unsafe name (e.g. `aria-label`) is coerced.
2026-05-05 09:34:26 -07:00
Kristiyan Kostadinov 39806360da refactor(compiler): add utility to check if property name needs to be quoted
Consolidates the places where we check if a property name should be quoted so we can reuse the logic.
2026-05-05 09:34:26 -07:00
Kam 1da396fd84 fix(docs-infra): mask page content leak at mobile nav right edge
On phones, the page content behind the primary-nav drawer leaks 1-2px past its right edge. Mask it with a 2px var(--page-background) box-shadow.
2026-05-05 09:31:53 -07:00
Kam 441a00d665 fix(docs-infra): keep mobile nav drawers usable on small screens
On phones, opening the primary-nav drawer left the page behind it scrollable, and the secondary drawer's mask had no explicit height so long submenus got clipped above the page content. Lock the page with overflow: clip on :host:has(.adev-nav-primary--open) for phone-only (preserves the primary nav's sticky context), give the secondary mask height: 100dvh on tablet-landscape-down so it fills the visible viewport, and align the nav-list :host height to 100dvh too so its inner scroll matches.
2026-05-05 09:31:26 -07:00
Kristiyan Kostadinov 6339d264eb fix(core): i18n flags leaking on errors
The i18n sub-system has the `changeMask` and `changeMaskCounter` flags which are set by i18n-related instructions and reset once the state is applied. The problem is that if something throws within the application logic, the flags would never be reset. This is currently causing flakes in our CI runs.

These changes resolve the issue by adding a try/finally around the flags.
2026-05-05 09:30:53 -07:00
Kristiyan Kostadinov 49748b5c79 fix(core): enforce return type for service factory
Updates the `factory` signature in `@Service` to enforce the type of the returned value.
2026-05-05 09:30:29 -07:00
Matthieu Riegler 71cc9e685c refactor(migrations): add a migration for optional chainings
This migration ensure that existing code is wrapped by the `$safeNavigationMigration` magic function when necessary to maintain the pre-exisiting behavior of exisiting optional chaining expressions.
2026-05-05 09:28:56 -07:00
Alex Rickabaugh 9b9769479b perf(forms): shortcut deepSignal writes if value is unchanged
Avoid deep write path traversal and triggering source signal updates
when calling `deepSignal.set(value)` with a new value that is
identical to the current value (`Object.is`).

This shortcuts the entire write path and unnecessary array/object
copying early on. This approach relies on the guarantee that `source`'s
value is non-nullable in the context where `deepSignal` is created and
used.

TAG=agy
CONV=9e5bd277-0d0a-466c-be36-5e3a8e6910be
2026-05-05 09:28:00 -07:00
Angular Robot 4f048e7de3 build: update dependency typescript to v6.0.3
See associated pull request for more information.
2026-05-04 13:05:58 -07:00
Alex Rickabaugh 0ea50ffe5a fix(forms): ensure debounced async validators produce pending status during debounce
When using a debounced async validator, the pending status from the internal
debounced resource was not flowing through to the resource created by the
factory. Replicate the 'chain' logic using the new privately exported ɵchain
function to propagate the loading status correctly.

Fixes #68105
2026-05-04 13:03:07 -07:00
Andrew Scott c84642ac16 feat(router): add unmatchedInputBehavior option to componentInputBinding
Introduce a new configuration option `unmatchedInputBehavior` to the `componentInputBinding` feature. This option allows users to configure the behavior when a component input is not matched by any key in the router data.

The available values are:
- 'alwaysUndefined': (Default) Always binds undefined to unmatched inputs.
- 'undefinedIfStale': Binds undefined only if the input was previously available in the router data for the active route in the outlet.

This feature addresses concerns raised in #63835 and #52946 regarding the retention of default values for inputs that were never targeted by the router, while still ensuring that stale data is cleared when a parameter is removed.
2026-05-01 16:04:52 -07:00
Angular Robot aab7dd48c0 build: update dependency bazel_lib to v3.3.1
See associated pull request for more information.
2026-05-01 16:04:14 -07:00
Sam Severance cd20dd07ce refactor(forms): improve clarity in SelectMultipleControlValueAccessor.writeValue
Rename the _optionMap forEach parameter from `o` to `id` and tighten its
type from `any` to `string`, removing the now-redundant `.toString()` call.
2026-05-01 16:02:34 -07:00
Matthieu Riegler b723734b72 refactor(migrations): fix incremental-hydration migration
Migration is now idempotent

fixes #68500
2026-05-01 16:01:28 -07:00
Nikolaos G. Ntaiko 429c665901 Fix typo in computed signals section 2026-05-01 16:00:48 -07:00
Matthieu Riegler 7c8c3347ef refactor(http): Add reportUploadProgress & reportDownloadProgress options
In order to raise an error on upload progress on the `FetchBackend`, we split `reportProgress` into 2 respective properties.

DEPRECATED: The `reportProgress` option is deprecated please use `reportUploadProgress` &  `reportDownloadProgress` instead.
2026-05-01 16:00:00 -07:00
Matthieu Riegler d91070ee4f refactor(devtools): cleanup
This are not the droids you are looking for.
2026-05-01 15:59:40 -07:00
tmpln 0ea27f4e65 fix(core): visit ng-let expression value in signal migration schematics
Before this fix, references to inputs inside @let statements were not
accounted for.
2026-05-01 15:59:15 -07:00
Kam c2f7403774 fix(docs-infra): exempt form validator names from API auto-linking
Add required, pattern, min, max, minLength and maxLength to LINK_EXEMPT
so FieldState property names stop auto-linking to the validator
functions of the same name.
2026-05-01 15:58:43 -07:00
Matthew Beck 0fa8f98f4f test: add NgModule compliance test with 'bootstrap' & local compilation
There was not a test demonstrating local compilation with the
'bootstrap' param on NgModule. This test adds one, among other NgModule
fields in one. These other fields are broadly covered already, but this
rolls them into one test exercising all fields.
2026-05-01 15:58:05 -07:00
Angular Robot fd8568f3c5 build: update alessbell/pull-request-comment-branch action to v2
See associated pull request for more information.
2026-05-01 15:57:44 -07:00
Angular Robot 9c7cbcd263 build: update all non-major dependencies
See associated pull request for more information.
2026-05-01 15:57:16 -07:00
Angular Robot 7ef1881d12 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-05-01 15:56:08 -07:00
SkyZeroZx 11721509b0 refactor(core): Makes @defer(hydrate ...) runtime tree-shakable
This commit updates `@defer` logic related to incremental hydration to be tree-shakable.

If hydrate triggers are used in a `@defer` block, the compiler emits a single top-level call to `ɵɵenableIncrementalHydrationRuntime`, placed once per create block before the first `ɵɵdefer` that requires it.

As a result, the incremental hydration runtime is only included in the bundle when hydrate is explicitly used.
2026-05-01 15:54:55 -07:00
Georgi Serev 9d803c51f4 feat(devtools): create a new settings menu
Create a new settings menu with more available space for new options and better organization and classification.
2026-05-01 15:54:26 -07:00
cexbrayat 1ab654cf28 fix(core): allow explicit read generic with signal input transforms
Using explicit single generic arguments with transforms (for example, input<boolean>(false, {transform: booleanAttribute})) previously failed overload resolution.

Before this fix, type-checking produced:
````
✘ [ERROR] TS2769: No overload matches this call.
  Overload 1 of 5, '(initialValue: boolean, opts?: InputOptionsWithoutTransform<boolean> | undefined): InputSignal<boolean>', gave the following error.
    Type '(value: unknown) => boolean' is not assignable to type 'undefined'.
  Overload 2 of 5, '(initialValue: undefined, opts: InputOptionsWithoutTransform<boolean>): InputSignal<boolean | undefined>', gave the following error.
    Argument of type 'true' is not assignable to parameter of type 'undefined'. [plugin angular-compiler]
```

This change adds specialized overloads for explicit read generics.
2026-05-01 15:53:56 -07:00
Alex Rickabaugh a4145dea06 Revert "fix(language-service): Add support for @Input with transforms"
This reverts commit dc9c72da9b. Reason: breaking
targets in g3.
2026-05-01 11:05:56 -07:00
Andrew Kushnir 2b624580e5 ci: update PullApprove config
This commit updates the PullApprove config to keep myself as a reviewer, but do not auto-assign PR reviews.
2026-04-30 16:13:18 -07:00
SkyZeroZx c5c35d992c docs: update @Service remove preview warning 2026-04-30 16:12:23 -07:00
Charles Lyding d4248ab89b docs: update angular developer skill and document migrations
Update the MCP documentation to reflect the removal of find_examples and modernize tools from the server. Add a new file documenting automatic migrations as the preferred alternative.
2026-04-30 16:11:50 -07:00
Alan Agius 116f55ce30 refactor(docs-infra): use Node.js temp APIs in deploy action
Replaces the 'tmp' package with native 'node:os' and 'node:fs' APIs to create temporary files in the system temp directory.
2026-04-30 16:10:54 -07:00
Alan Agius 0fcc120a95 refactor: remove tools/contributing-stats
Removes the tools/contributing-stats directory which is no longer used.
2026-04-30 16:10:54 -07:00
Alan Agius 62d19b5531 refactor: remove tools/legacy-saucelabs
Removes the tools/legacy-saucelabs directory which is no longer used.
2026-04-30 16:10:54 -07:00
Alan Agius b7230f398c refactor: remove karma-js.conf.js
Removes the karma-js.conf.js file and its reference in BUILD.bazel.
2026-04-30 16:10:54 -07:00
Alan Agius 9fa673aeed refactor: remove .clang-format
Removes the .clang-format file from the repository.
2026-04-30 16:10:54 -07:00
Matthieu Riegler 8f94892a71 docs: add section about variable scopes
This is mostly a copy of the section we had on aio.
2026-04-30 16:10:28 -07:00
Kristiyan Kostadinov 7aad302c3e fix(core): mark service decorator as stable
Marks `@Service` as stable for v22.
2026-04-30 16:08:27 -07:00
Matthieu Riegler 28d38b582c refactor(common): update deprecation message
The old control flow is very much not recommended but we're not ready to remove it in v22.
2026-04-30 16:06:57 -07:00
Angular Robot ebffd80ce4 build: update all github actions
See associated pull request for more information.
2026-04-30 15:55:07 -07:00
Matthieu Riegler bc637a304f refactor(core): add support for default exports to injectAsync
ex:
```
await injectAsync(() => import('./test_service'))
```

We'll be reusing the features that were already used by the router to support components lazy-loading.
2026-04-30 15:53:07 -07:00
Angular Robot 9dc4e44eea build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-30 15:52:21 -07:00
Matthieu Riegler dc9c72da9b fix(language-service): Add support for @Input with transforms
Prior to this change @Input with transforms were not linked by language service and you couldn't navigate on it.
2026-04-30 15:51:48 -07:00
Alan Agius 9d7a609458 fix(core): validate security-sensitive attributes in i18n bindings
Ensures that security-sensitive attributes (e.g., sandbox, allow) are correctly validated when applied through i18n-* dynamic attribute bindings, preventing potential policy bypasses.

Closes #68418
2026-04-30 15:47:12 -07:00
Andrew Scott d919f9a13e refactor: attempt stronger automatic comment blocking
Updates the PR review skill to have stronger language against automatic comment posting
without explicit approval
2026-04-30 15:45:40 -07:00
hawkgs 9fa4be9d09 test(zone.js): vitest patch for testing (#68395)
Test `fakeAsync` API in Vitest when Zone.js `vitest` patch applied.

PR Close #68395
2026-04-30 15:44:35 -07:00
Charles Lyding 62c6e3b7ee feat(zone.js): support vitest patching in zone.js/testing (#68395)
To support `fakeAsync` usage while using `vitest` as a test runner, Zone.js
now provides patching when using the `zone.js/testing` package import.
This patching is similar to that of the existing jasmine, mocha, and jest
functionality.

PR Close #68395
2026-04-30 15:44:35 -07:00
wowDAS Markus Ramšak 6aa40f6c04 docs: fix typo in CHANGELOG.md 2026-04-30 15:43:30 -07:00
Matthieu Riegler 6413e703fa refactor(http): refactor http options
Use shared types to ease maintenance of the http client apis.

fixes #64513
2026-04-30 15:42:32 -07:00
Alex Rickabaugh e0536091f5 perf(forms): optimize reactivity by using shallow array equality
Add `shallowArrayEquals` to computed signals returning arrays of errors or reasons in Signal Forms. This prevents unnecessary downstream invalidations when the content of the arrays remains unchanged.
2026-04-30 15:41:45 -07:00
Sonu Kapoor 4c9afb68a3 fix(core): respect ngSkipHydration on components with projectable nodes in LContainers
When a component is created dynamically via ViewContainerRef.createComponent
and receives projectable nodes (e.g. raw DOM nodes or embedded view root nodes),
applying ngSkipHydration to its host element did not prevent NG0503 from being
thrown during SSR serialization.

The root cause is an asymmetry in the serialization pipeline. For inline child
components, serializeLView already guards the annotateHostElementForHydration
call with a ngSkipHydration attribute check, so the component's lView is never
serialized when hydration is opted out. For components hosted inside an
LContainer (created via ViewContainerRef.createComponent), serializeLContainer
called serializeLView unconditionally — bypassing that guard entirely. When
serializeLView then encountered a projection slot backed by a raw DOM node
array, it threw NG0503 regardless of the ngSkipHydration flag.

The fix adds the same guard inside serializeLContainer before calling
serializeLView: if the child lView belongs to a component whose host element
carries ngSkipHydration, the lView serialization is skipped. This matches the
existing behavior for inline components and allows the documented workaround to
actually work for dynamically created ones.

Fixes #67928
2026-04-29 16:09:14 -07:00
Andrew Scott 2eae497a04 feat(compiler-cli): support external TCBs with copied content in specific mode
This change adds a new  that allows environments that cannot support inline TCBs (such as the language service or source-to-source transforms where TS compilation and emit are downstream) to still perform template type checking.

    Instead of inlining the TCB into the original source file when non-exported symbols are referenced, we now copy the file content to the .ngtypecheck.ts shim file and generate the external TCB there, if requested by the inlining mode. This preserves the local scope of the original file while keeping the original file unmodified.
2026-04-29 16:08:33 -07:00
Alon Mishne 12d4844c8b release: cut the v22.0.0-next.10 release 2026-04-29 16:03:12 -07:00
Alon Mishne 662560effc docs: release notes for the v21.2.11 release 2026-04-29 15:40:46 -07:00
Kam 13c0422029 docs(docs-infra): open update guide external links in new tabs
External links in the update guide opened inconsistently. Override
marked's link renderer to add `target="_blank" rel="noopener noreferrer"`
to external anchors and apply the `external-link-with-icon` mixin for
the icon. Convert raw HTML and bare URLs in recommendations.ts to
markdown so they all flow through the renderer.
2026-04-29 13:59:42 -07:00
Kam 2101b13653 docs: document allowedHosts SSR requirement in v21 update guide
The GHSA-x288-3778-4hhx patch requires `allowedHosts` on
`CommonEngine` or SSR silently falls back to CSR. Add a checklist
item to the v21 update guide.
2026-04-29 13:59:12 -07:00
Angular Robot 82890dd9f5 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-29 13:58:03 -07:00
Andrew Scott af24a4ae3a fix(vscode-extension): Look for tsdk override in the new js/ts.tsdk.path setting
recent versions of vscode use js/ts.tsdk.path rather than typescript.tsdk

relates to #68423
2026-04-29 13:39:15 -07:00
Bhuvansh855 9f7d41f296 docs: improve clarity in dependency injection guide 2026-04-29 13:38:17 -07:00
Alan Agius 0f7086add4 docs: update documentation for platform server URL token options
This `baseUrl` option is not available.
2026-04-29 13:36:59 -07:00
Andrew Scott c70625e806 refactor(compiler-cli): remove reflectionhost from environment
all necessary info is already available in the tcb meta objects. environments without full ts program no longer need a reflectionhost for tcb generation
2026-04-29 13:36:21 -07:00
splincode 54a985c5ca refactor(forms): replace any with unknown in interop control value types
- `CombinedControl.value` and `InteropNgControl.value` getter now return
  `unknown` instead of `any`, matching the actual `ReadonlyFieldState<unknown>`
  return type of `controlValue()`.
- Remove redundant `as any` cast in `cvaControlCreate`: `parent` is typed as
  `FormField<unknown>`, so `state().controlValue` is `WritableSignal<unknown>`
  and accepts `unknown` directly.
2026-04-29 13:35:48 -07:00
Ben Hong 18826de489 docs: add debouncing section to signal forms async operations
Co-authored-by: Matthieu Riegler <kyro38@gmail.com>

Co-authored-by: Matthieu Riegler <kyro38@gmail.com>

Co-authored-by: Matthieu Riegler <kyro38@gmail.com>
2026-04-29 13:35:18 -07:00
Angular Robot 37ba0a79a6 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-29 13:34:08 -07:00
Matthieu Riegler 37ec63e745 refactor(compiler): introduce default constant for legacyOptionalChaining flag
This will help patch the value in G3 to help land this change.
2026-04-29 10:01:13 -07:00
Matthieu Riegler 2896c93cc1 feat(compiler): Angular expressions with optional chaining returns undefined
To mitigate this breaking change,  this behavior can be disabled by wrapping expressions with the `$null` magic function.
: `$null(foo?.bar?.baz)`
2026-04-28 15:26:53 -07:00
Matthieu Riegler ef38017418 build: move devtools only deps out of the workspace
This reduces the clutering of the workspace package.
2026-04-28 13:05:33 -07:00
aparziale 8f8972b0fd feat(migrations): model + output migrations
becomes input + linkedSignal

When a component has both a model() property and a conflicting output property (e.g., foo model + fooChange output), this migration converts the model() to an input() + linkedSignal() pattern to avoid naming conflicts.

Fixes #67340
2026-04-28 12:43:55 -07:00
SkyZeroZx 97cac1cf4d fix(common): prevent focus from scrollToAnchor
Focus the target element using `focus({preventScroll: true})` after scrolling, so the browser doesn’t adjust the scroll position when applying focus.

Fixes #65938
2026-04-28 12:39:26 -07:00
Angular Robot f5b139f5b8 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-28 12:33:28 -07:00
Denis Balan 5dfe37df8e docs: Fix links to Firebase AI Logic Angular example 2026-04-28 12:10:48 -07:00
Suraj Yadav f2c6445681 docs(forms): add NG01902 error reference and link to docs
Add the NG01902 (Orphan field in signal forms) documentation page
to the Error Encyclopedia and change the ORPHAN_FIELD_PROPERTY
error code to -1902 so Angular's RuntimeError automatically appends
a link to angular.dev/errors/NG01902 in the thrown error message.
2026-04-28 12:07:46 -07:00
Matthieu Riegler 8c11816490 fix(core): fix ordering of view queries metadata in JIT mode
AOT was generating an array that was ordered as signal queries first, then the decorator queries.
Aligning JIT with AOT fixes the issue illustrated by the test.

fixes #68404
2026-04-28 12:03:41 -07:00
Kam a6eb55642c docs: use contentChildren() in component harness example
The example already uses the signal-based input() but still declares
items with the @ContentChildren decorator. Convert to the signal-based
contentChildren() query for consistency.
2026-04-28 12:03:09 -07:00
Matthieu Riegler 444b024d49 feat(core): Add a injectAsync helper function
The commit introduces a new function to assist users who want to lazy load services and use the DI system to create them.

Example:

```ts
import {injectAsync} from 'angular/core';

class MyCmp {
  someSvc = injectAsync(() => import('..'));

  async onClick() {
    (await this.someSvc()).handleClick();
  }
}
 ```
2026-04-28 12:01:27 -07:00
Alon Mishne 0c56679049 build: lock file maintenance
Updated the pnpm-lock.yaml file to ensure all dependencies are up to date and consistent.
2026-04-28 11:55:09 -07:00
hawkgs 6abdef4f4f docs: add information about zone.js Vitest patch in the Vitest migration guide
Update the Karma to Vitest migration guide to include information about the zone.js Vitest patch that should handle `fakeAsync`.

Related to #68395.
2026-04-28 10:32:49 -07:00
Joey Perrott e4f9781f28 build(dev-infra): update dev-infra actions to latest commit
Updates all GitHub Actions that use actions from the angular/dev-infra repository to the latest commit SHA 442c2fcbf06a321b5196b4c5fc70e78a49242958.
2026-04-28 10:32:20 -07:00
Kristiyan Kostadinov 72be5be9c1 refactor(compiler-cli): remove checkTwoWayBoundEvents flag
Removes the `checkTwoWayBoundEvents` flag since the code it generates is quite breaking and we never got the chance to enable it. Also it caused our tests to misrepresent how the compiler behaves for actual users.
2026-04-28 10:31:42 -07:00
Kam 273ff07469 docs: use inject() in @Self example in hierarchical DI guide
The surrounding @SkipSelf and @Host examples already use inject(),
and the section intro recommends it. Align the @Self example to match.
2026-04-28 10:30:57 -07:00
Herdiyan IT Dev f219e65841 refactor(dev-infra): use shell: false and quote args in benchmark-compare workflow
Currently, the exec() utility uses childProcess.spawn() with shell: true. This commit changes the spawn option to shell: false to prevent OS command injection vulnerabilities and quotes the benchmark target in the github action.
2026-04-28 10:29:24 -07:00
Angular Robot 32d768f69c build: lock file maintenance
See associated pull request for more information.
2026-04-28 10:25:45 -07:00
Angular Robot 52bcec1ae4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-28 10:19:56 -07:00
Alan Agius 1bfdae91aa docs: document NG_TRUST_PROXY_HEADERS environment variable for AngularNodeAppEngine
See: https://github.com/angular/angular-cli/pull/33056 for more info.
2026-04-28 10:11:12 -07:00
Simon c8aad6acc6 docs: remove duplicated text 2026-04-27 17:10:19 -07:00
Simon 38c352766a docs: remove spaces to correct the indentation 2026-04-27 17:09:45 -07:00
Kristiyan Kostadinov 6bd1721662 fix(compiler): let declaration span not including end character
Fixes that the span for `@let` declarations didn't include the end token.
2026-04-27 17:09:14 -07:00
Alan Agius 2a6b6fafb0 fix(platform-server): ensure origin has a trailing slash when parsing url
The origin did not have a trailing slash, which caused parsing issues for relative URLs.

Fixes #68322
2026-04-27 17:08:36 -07:00
aparziale 982e3cce52 docs: Fix typo in doc
Fix typo in documentation. Changed "create workspace" to "create a workspace"

Fixed #68375
2026-04-27 17:08:02 -07:00
Sonu Kapoor 3583c01bf9 fix(core): guard against non-object events and avoid listener wrapper identity mismatch
Two issues caused browser test failures after the event replay fix:

1. `markEventHandledForElement` used the event object as a WeakMap key, but
   `DebugElement.triggerEventHandler` can pass null or primitive values as the
   event argument. Added an early return for non-object values.

2. Registering a separate `domListener` closure with `renderer.listen` instead of
   `wrappedListener` caused `DebugElement.triggerEventHandler` to invoke the
   handler twice: once via `this.listeners` (which holds `wrappedListener`) and
   once via Zone.js's `eventListeners` (which holds the unwrapped `domListener`).
   The existing dedup logic in `triggerEventHandler` checks if the unwrapped
   Zone.js listener is already in `invokedListeners`, but with two different
   function objects that check always fails.

   Replaced the `domListener` wrapper with a property (`__ngNativeEl__`) stored
   directly on `wrappedListener`. `wrapListenerIn_markDirtyAndPreventDefault` reads
   this property and calls `markEventHandledForElement` when the listener fires,
   while `renderer.listen` receives the same `wrappedListener` function that
   Angular stores in `lCleanup`, preserving the dedup invariant.
2026-04-27 17:07:36 -07:00
Sonu Kapoor d5fd51e956 fix(core): prevent event replay double-invocation when element hydrates before app stability
When `withEventReplay()` is enabled and a component hydrates before the
application becomes stable (e.g. while a pending HTTP request is in
flight), a user interaction on the hydrated element triggers both the
real DOM listener registered by Angular and the jsaction replay path.
This causes the event handler to be invoked twice.

The root cause is that `listenToDomEvent` registers the same
`wrappedListener` both as a stashed jsaction handler (via
`stashEventListenerImpl`) and as a native DOM listener (via
`renderer.listen`). When the user interacts after hydration but before
app stability, jsaction queues the event because no dispatcher is
registered yet. Once the app stabilises and `initEventReplay` runs,
jsaction replays the queued event through `invokeListeners`, which
calls the stashed handler a second time.

The fix tracks dispatched `(event, element)` pairs in a
`WeakMap<Event, WeakSet<Element>>`. The native DOM listener wrapper
records each pair via `markEventHandledForElement`, and `invokeListeners`
skips replay for any pair already present. Keying by element (rather
than event alone) preserves incremental hydration behaviour, where
jsaction legitimately replays the same event on a different element
(the deferred block content) from the one that originally triggered
hydration.

Fixes #67328
2026-04-27 17:07:36 -07:00
Kam 67a5f00cd8 docs: document moduleResolution bundler change in v20 update guide
The v20 update guide doesn't flag that `ng update` switches
`moduleResolution` to `'bundler'`. Add a checklist item so manual
upgrades don't miss it.
2026-04-27 17:06:35 -07:00
Matthieu Riegler 4ad3a1fe37 refactor(core): Don't throw when there are not async metadata
In the context of AOT tests, component with defer blocks no longer throw on instanciation if the component is not overridden (with `overrideComponent`)

Prior to this change, all components with a `@defer` block would throw if `compileComponents` was not invoked.

In none-JIT apps, this change makes `compileComponents()` uneccesary.
2026-04-27 17:04:09 -07:00
Andrew Scott f17f32c351 docs(router): Fix method name for retrieving stored handles
method name was documented incorrectly. this fixes the name
2026-04-27 17:03:21 -07:00
aparziale ded5a0ed62 docs: Align Router API docs with inject based DI
Updates Router documentation examples to reflect modern inject based dependency injection instead of constructor injection.

Fixed #68378
2026-04-27 17:02:28 -07:00
SkyZeroZx d2c7b4e111 docs(docs-infra): Validate case-sensitive API symbol links in @link
Adds build-time validation for case-sensitive API symbols in `@link`. Avoid broken links
2026-04-27 17:01:40 -07:00
SkyZeroZx 70c011e879 refactor(compiler): Removes unused compiler utility functions
Remove helper functions and constants across the compiler, as they are no longer required by current logic.
2026-04-27 17:00:44 -07:00
Andrew Scott 357cb15208 refactor: use stronger language for adev writing guide
use stronger language to improve skill usage hits for adev writing.
2026-04-27 15:29:04 -07:00
Angular Robot da94272eed build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-27 15:26:58 -07:00
Angular Robot 08930e60bb docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-24 15:58:24 -07:00
Angular Robot ac9babec96 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-24 13:31:56 -07:00
Kam 29081f7765 docs(docs-infra): improve Playground card on installation page
Updates the Playground card copy and adds a `titleInline` attribute on
<docs-card> so the icon and title sit on the same row. Existing cards
are unaffected.
2026-04-24 10:34:38 -07:00
SkyZeroZx adbd1ab3f0 docs: update service documentation to include @Service decorator details 2026-04-24 10:12:31 -07:00
Angular Robot f9c1f979d9 build: update pnpm to v10.33.2
See associated pull request for more information.
2026-04-24 10:10:56 -07:00
Angular Robot 9203aca433 build: update devinfra digest to c4d0c37
See associated pull request for more information.
2026-04-24 10:06:14 -07:00
Alan Agius 0399115a82 docs: document trustProxyHeaders and update X-Forwarded-Prefix validation
Update the security guide to explain how to configure `trustProxyHeaders` when initializing the application engine. Also, update the validation rules for `X-Forwarded-Prefix` to reflect that it must start with `/` and contain only alphanumeric characters, hyphens, and underscores.
2026-04-24 10:03:56 -07:00
Angular Robot 65c205dc34 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-23 15:11:57 -07:00
Angular Robot 218e2d0240 build: update cross-repo angular dependencies to v22.0.0-next.6
See associated pull request for more information.
2026-04-23 14:13:04 -07:00
Angular Robot 5b4453b312 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-23 12:40:33 -07:00
Kam 6120d3196a docs: link Angular CLI in installation prerequisites
Links the "Angular CLI" mention in the Terminal prerequisite to the CLI
overview page.
2026-04-23 11:39:38 -07:00
Matthieu Riegler b2083a7fd2 build: cleanup workspace deps
Some of the deps are move down to the only targets that uses them.
2026-04-23 11:38:26 -07:00
Matthieu Riegler 789cbd58b8 refactor(devtools): drop the semver-dsl page
We can use the semver package directly.
2026-04-23 11:37:30 -07:00
Cameron Smick e96673ff64 refactor(devtools): make the DevToolsNode directives property optional
Client-Only Wiz doesn't have the concept of a directive. Once the new ng.getComponentForest function is implemented, Client-Only Wiz cowilluld provide `ComponentTreeNode`s without a `directives`` property. This change supports that case by making the `directives` property optional.
2026-04-23 11:36:00 -07:00
Matthieu Riegler c77f16de93 refactor(devtools): Use @Service instead of @Injectable
Dogfooding is always a good idea.
2026-04-23 11:30:12 -07:00
Matthieu Riegler 74143523d5 docs(docs-infra): Use @Service instead of @Injectable
Dogfooding is always a good idea.
2026-04-23 11:21:40 -07:00
SkyZeroZx 562d920342 docs: update Defer Trigger Misconfiguration with new examples 2026-04-23 11:18:01 -07:00
Leon Senft c64ee96e0c release: cut the v22.0.0-next.9 release 2026-04-22 16:50:38 -07:00
Leon Senft 602fe93e0f docs: release notes for the v21.2.10 release 2026-04-22 16:33:11 -07:00
Matthieu Riegler 7f3f3d7da1 ci: remove remainings of saucelabs tests
Those haven't been used for a while.
2026-04-22 14:41:03 -07:00
Matthieu Riegler 3377b8cd6b ci: remove tslint rules
These rules aren't really needed, it also helps us cleanup our deps
2026-04-22 14:39:14 -07:00
Savio Dsouza 8f5e0e09e9 build: pin firebase-tools version and disable credential persistence in preview deploy workflow 2026-04-22 14:38:22 -07:00
Suraj Yadav 2c141c04cb refactor(compiler-cli): simplify Angular decorator stripping
Removes redundant decorator-stripping branches and consolidates
the transformation flow to reduce complexity and improve readability.
2026-04-22 11:07:35 -07:00
Angular Robot 271dd4d933 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-22 11:04:19 -07:00
Kristiyan Kostadinov 8f3d0b9d97 feat(core): introduce @Service decorator
These changes introduce the new `@Service` decorator which is a more ergonomic alternative to `@Injectable`. The reason we're adding a new decorator is that `@Injectable` has been around since the beginning of Angular and it has a lot of baggage that adds unnecessary overhead for users that generally want to define a singleton service, available in their entire app. The key differences between `@Service` and `@Injectable` are:
1. `@Service` is `providedIn: 'root'` by default. You can opt into providing the service yourself by setting `autoProvided: false` on it.
2. `@Service` doesn't allow constructor-based injection, only the `inject` function.
3. `@Service` doesn't support the complex type signature of `@Injectable` (`useClass`, `useValue` etc.). Instead it supports a single `factory` function.

Example:

```ts
import {Service} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {AuthService} from './auth';

@Service()
export class PostService {
  private readonly httpClient = inject(HttpClient);
  private readonly authService = inject(AuthService);

  getUserPosts() {
    return this.httpClient.get('/api/posts/' + this.authService.userId);
  }
}
```
2026-04-22 11:01:01 -07:00
Rishabhdeep Singh b395173cf2 fix(migrations): fix NgClass leaving trailing comma after removal
This fixes an issue where when removing NgClass from the imports array of a component, an extra trailing comma would be left behind if it was the last element in that component`.
2026-04-22 09:59:49 -07:00
Rishabhdeep Singh 27f021248d fix(migrations): fix NgClass leaving trailing comma after removal
This fixes an issue where when removing NgClass from the imports array of a component, an extra trailing comma would be left behind if it was the last element in that component`.
2026-04-22 09:59:49 -07:00
Angular Robot 09b9a62a25 build: lock file maintenance
See associated pull request for more information.
2026-04-21 11:52:07 -07:00
Angular Robot 28760bd050 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-21 10:21:43 -07:00
Joel Kesler b24b4cb699 fix(docs): link formatting in "Animating your Application with CSS"
One of the links in `Animating your Application with CSS` page has a formatting bug for one of it's links.
2026-04-21 10:20:05 -07:00
Bhuvansh855 8ca07f171a docs: improve wording and consistency in http documentation 2026-04-21 10:17:26 -07:00
Nikhil Bachani ac92a8aae8 docs: fix tracking expression reference in NG0955.md
Corrected the tracking expression reference from 'item.key' to 'item.value' in the explanation of duplicate keys.
2026-04-21 10:14:47 -07:00
Matthieu Riegler fa6a3d208d docs: update builder docs
We use `@angular/build` today.
2026-04-21 09:02:31 -07:00
Matthieu Riegler 1f52ea83ab build: removing unused deps
They were unused (at least at the workspace level), we can remove them from there.
2026-04-21 09:01:15 -07:00
SkyZeroZx 6eff439546 fix(router): restore internal URL on popstate when browserUrl is used
Fixed an issue where back/forward (`popstate`) navigation attempted to match the displayed `browserUrl` instead of the internal route, which could result in `NG04002: Cannot match any routes`.

Fixes #67549
2026-04-20 16:46:25 -07:00
Kam d27e2c24e1 docs: warn against storing secrets in environment files
Add a CRITICAL callout warning that files in `src/environments/`
ship to the client and should not hold secrets like API keys.
2026-04-20 13:29:13 -07:00
Kam c04c0b977a docs(docs-infra): guard sandbox reset before initialization in playground
changeTemplate() was calling reset() on the sandbox before init()
completed, causing a TypeError when spawning processes on an
uninitialized WebContainer. Add isSandboxReady signal to skip
reset until the sandbox is fully initialized.
2026-04-20 13:17:17 -07:00
Kam 3293ced401 docs(docs-infra): add Angular Aria accordion playground template
Adds a single-expansion accordion playground template under
adev/src/content/tutorials/playground/5-aria-accordion demonstrating the
Angular Aria primitives. Wires @angular/aria into the editor TypingsLoader
so imports resolve in the sandbox.
2026-04-20 13:15:59 -07:00
Kam 2dc3ab596b docs(docs-infra): adjust close button spacing in mobile navigation
Use relative positioning to offset the close button from the top edge without affecting the layout of surrounding elements.
2026-04-20 13:14:34 -07:00
Matthieu Riegler 13be2961f6 ci: remove disabled side-effects integration tests
This test was disabled 5+ years ago, we probably don't need it anymore.
2026-04-20 13:13:22 -07:00
Bhuvansh855 74a7d6b8f9 docs: improve wording and consistency in forms documentation 2026-04-20 13:12:29 -07:00
Andrew Scott 9f479ae964 feat(core): Update Testability to use PendingTasks for stability indicator
Since angular@12181b9, zone stability
contributes to the PendingTasks. There is now a single source of truth for application stability
tracked in PendingTasks. This change makes protractor's whenStable compatible with zoneless.
The `Router` and `HttpClient` also contribute to stability using the
`PendingTasks` injectable. There will likely be more updates in the
future to have more features contribute to stableness in a zoneless
compatible way.

This update uses PendingTasks for stability by default when ZoneJS is not present or
can be enabled with an option when ZoneJS is present (but otherwise ignored with ZoneJS).

fixes #68180
2026-04-20 13:08:43 -07:00
SkyZeroZx 3ae40e6685 refactor(core): complete removal of deprecated createNgModuleRef alias
Finalize the cleanup by removing the remaining `createNgModuleRef` alias.
2026-04-20 12:09:45 -07:00
Bhuvansh855 c610425310 docs: fix wording in reactive forms guide 2026-04-20 09:51:41 -07:00
Bhuvansh855 a718e188c6 docs: improve clarity in dynamic forms guide 2026-04-20 09:30:44 -07:00
Angular Robot a0d45639a9 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-17 15:14:59 -07:00
aparziale d771a65ac0 refactor: Improve hydration mismatch errors for third-party scripts
Improves error messages shown during hydration mismatches to better
surface cases where third-party scripts or browser extensions have
modified the DOM outside of Angular's control.

Fixed #59224
2026-04-17 14:33:10 -07:00
Angular Robot 279fd7d882 build: update bazel dependencies
See associated pull request for more information.
2026-04-17 14:31:53 -07:00
Andrew Scott 17d10f7a99 fix(router): set default paramsInheritanceStrategy to 'always'
Set the default value of paramsInheritanceStrategy to 'always'. This change ensures that route parameters are inherited from parent routes by default, which is the behavior most users expect. It simplifies routing configuration for the majority of use cases.

This change aligns Angular with other popular routing systems where child routes automatically have access to parent parameters:
- React Router: useParams() includes parent params.
- Vue Router: $route.params includes parent params.
- Next.js: params are passed to nested layouts and pages.
- TanStack Router: useParams() includes parent params with full type safety.

BREAKING CHANGE: paramsInheritanceStrategy now defaults to 'always'

The default value of paramsInheritanceStrategy has been changed from 'emptyOnly' to 'always'. This means that route parameters are inherited from all parent routes by default. To restore the previous behavior, set paramsInheritanceStrategy to 'emptyOnly' in your router configuration.
2026-04-17 14:27:43 -07:00
Angular Robot 56ff89c92d build: update all non-major dependencies
See associated pull request for more information.
2026-04-17 14:26:35 -07:00
pravintargaryen da6c92eccd docs: add inject to structural directive imports 2026-04-17 14:25:04 -07:00
Angular Robot 421986e49b docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-17 14:24:30 -07:00
Angular Robot 67e4d19597 build: update all github actions
See associated pull request for more information.
2026-04-17 10:54:09 -07:00
Michael Small 0850e20a83 docs: capitalize FormField in form-logic.md imports: [...] 2026-04-17 10:50:51 -07:00
Michael Small 4da3f6c432 docs: fix rxResource example of validateAsync 2026-04-17 10:49:51 -07:00
Christian Oliff bf4faed626 docs: Fix typo in menubar.md
manubar > menubar
2026-04-17 10:49:15 -07:00
Kam 9c30e74349 docs: fix typo in what-is-angular page
Change "language services powers" to "language service powers".
2026-04-17 10:48:30 -07:00
kirjs 3579ea0850 docs: release notes for the v19.2.21 release 2026-04-16 01:23:00 +03:00
kirjs 9bead58c8b docs: release notes for the v20.3.19 release 2026-04-16 01:10:21 +03:00
kirjs c326548382 release: cut the v22.0.0-next.8 release 2026-04-16 01:00:28 +03:00
kirjs 05a851ec7f docs: release notes for the v21.2.9 release 2026-04-16 00:37:13 +03:00
Matthieu Riegler 4e331062e8 feat(core): allow synchronous values for stream Resources
In order for resources to allow caching in SSR context (eg in the TransferState), resource need to be able to set their value synchronously.

If the resource value is not set synchronously, the resource will be in in a "loading" state which is responsible for destroying the server-hydrated resolved DOM.
2026-04-16 00:13:04 +03:00
arturovt 79c981840f docs(router): document .. traversal and relativeTo pitfalls in router.navigate()
Explain two non-obvious behaviors of the commands array in router.navigate():

- Multiple '..' segments must be combined in the first array element
  (e.g. ['../../foo']), not spread across separate elements
  (e.g. ['..', '..', 'foo']), because the router only parses '..'
  from the first command string. Subsequent elements are treated as
  literal path segments, causing a navigation error.
- A leading '/' in the first command makes navigation absolute and
  silently ignores the relativeTo option entirely.

Closes #65657
2026-04-15 22:40:42 +03:00
Angular Robot 034b12ffd7 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-15 20:22:48 +03:00
SkyZeroZx 281a2dba78 docs: Add guide for debounced signals
Add guide for `debounced` signals.
Also add `@see` tags
2026-04-15 20:04:10 +03:00
Kristiyan Kostadinov 7fa274510f refactor(compiler): move TCB generation logic into compiler
Moves the logic for generating type check blocks into the compiler since it isn't coupled to TypeScript anymore.

Note: the tests haven't been moved over, because they depend on the environment that's currently in `compiler-cli` and it still has some dependencies on TypeScript.
2026-04-15 19:43:29 +03:00
Ben Hong 50a3b0e1ba docs: add new signal forms - form submission guide 2026-04-15 19:38:35 +03:00
Matthieu Riegler a46c64758e docs: fix bootstraping link
fixes #68212
2026-04-15 19:25:35 +03:00
Angular Robot a8132eb2fe docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-15 19:24:48 +03:00
Angular Robot 8b4581d1bb build: lock file maintenance
See associated pull request for more information.
2026-04-15 10:49:13 -04:00
Suleiman Yunus e32159b5c5 docs: correct "What to learn more about Angular?" to "Want to learn more about Angular?" 2026-04-15 10:33:25 -04:00
arturovt fc6a7eea68 fix(zone.js): allow draining microtasks in Promise.then (through flag)
These changes are essentially the same as those introduced in
angular#45273, but they include backward compatibility
for applications that explicitly rely on the order in which microtasks are drained.

This is critically important for our code and other third-party code, which is
beyond our control, to work properly. If a microtask is scheduled within an event
listener to be executed "later", it should indeed be executed later and not synchronously,
as this would break the expected flow of code execution.

The simple code that reproduces the behavior that exists now:

```ts
Zone.current.fork({name: 'child'}).run(() => {
  const div = document.createElement('div');
  div.style.height = '200px';
  div.style.width = '200px';
  div.style.backgroundColor = 'red';
  document.body.appendChild(div);

  function listener() {
    Promise.resolve().then(() => {
      div.style.height = '400px';
    });
  }

  div.addEventListener('fakeEvent', listener);
  div.dispatchEvent(new Event('fakeEvent'));
  console.log(div.getBoundingClientRect().height); // 400
});
```

The code above logs 400 as the height, but it should actually log 200 because the
height is updated in a microtask within the event listener.

When using Angular with microfrontend applications, especially when other apps might be
using React, zone.js can disrupt the classical order of operations. For example, when using a
`react-component/trigger`, it schedules a microtask within an event listener using
`Promise.resolve().then(...)` to determine whether the event needs to be re-dispatched.
The event is re-dispatched when the layout has changed, which is why a microtask is used.

With this change, we introduce a global configuration flag,
`__zone_symbol__enable_native_microtask_draining`, to allow consumers to enable
microtask draining within a browser microtask.

This flag is necessary to prevent any breaking changes resulting from this modification.
The previous attempt to address this issue caused a significant number of failures in g3.
Therefore, we are hiding that fix behind the configuration flag.

Closes angular#44446
Closes angular#55590
Closes angular#51328
2026-04-15 10:31:28 -04:00
Kam b2cff7918d docs(docs-infra): add background to playground template dropdown
The template dropdown menu had no background color on the container,
causing page content to bleed through behind menu items.
2026-04-15 10:26:05 -04:00
Alan Agius ede7c58a2a fix(platform-server): prevent SSRF bypasses via protocol-relative and backslash URLs
The `parseUrl` function in `ServerPlatformLocation` uses `new URL(urlStr, origin)` to parse incoming request URLs during SSR. Per the WHATWG URL specification, protocol-relative URLs (`//evil.com`) and backslash-prefixed URLs (`/\evil.com`) can override the hostname component of the base URL.

This vulnerability typically manifests in SSR setups (e.g., Express) where `req.url` is passed directly to `renderApplication` or `renderModule`:

```typescript
// Example usage in an Express server handling: http://localhost:4000//evil.com
app.get('*', async (req, res) => {
  const html = await renderApplication(bootstrap, {
    document: template,
    url: req.url, // req.url is "//evil.com"
  });
  res.send(html);
});
```
2026-04-15 10:23:52 -04:00
Ben Hong 3eba900d3f docs: add new signal forms schema guide 2026-04-15 10:22:35 -04:00
Matthieu Riegler d1cd97648a fix(http): Don't on Passthru outside of reactive context
Priori to this change, the InMemory API threw when request was emited outside an injection context and that request hit the passThru.
This commit fixes this.
2026-04-15 10:20:48 -04:00
Angular Robot 5eee59406b build: update dependency diff to v9
See associated pull request for more information.
2026-04-15 10:20:07 -04:00
Doug Parker 75f2cb8f56 feat(core): implement Angular DI graph in-page AI tool
This creates a new `angular:di-graph` in-page tool which returns the entire dependency injection graph for the application.

We use the following rough algorithm for discovering all element injectors:
1. Find all root `LView` objects by querying for `[ng-version]`.
2. Walk all the transitive `LView` descendants of the roots.
3. Filter these `LView` objects to just directives.
4. Find the injector for a given directive and walk up its ancestors to find all element injectors.

Discovering environment injectors works mostly the same way, just following the environment injector graph instead.

This approach has a few known limitations which are out of scope for the moment:
1. Any given component typically has both an element injector *and* an environment injector. The relationship of "component -> environment injector" is not expressed in the result as of now, meaning the AI doesn't really have any insight into _which_ environment injector is being used for a particular component, though the injector will be one of the returned values.
2. The implementation does not support MFE use cases of multiple applications on the page at the same time.
3. The performance is not ideal, as we walk `LView` descendants twice and walk up the injector tree for every directive, repeatedly covering the same scope (ideally we'd just walk up every *leaf* directive, which would cover the same result for less effort). However for a debug tool, this is likely fine for now and we can optimize later if/when it becomes necessary.

I did consider reusing more of the existing implementation in `global_utils` which exists to support Angular DevTools (we are already using some of it), however the existing support in `@angular/core` is actually fairly limited, returning very primitive data structures and relying on Angular DevTools to do the heavier lifting of collapsing the code into a usable graph representation. There's a potential path in the future to converge these implementations and potentially have `global_utils` use some of this code instead, but I will leave that for a future cleanup effort.
2026-04-14 18:35:51 +03:00
Doug Parker de03e83980 refactor(core): add walkLViewDirectives
This walks all transitive descendant directives via the `LView` structure of the given input. This is a generic utility, but useful for finding all components in a tree to look for their associated `Injector` objects.

One known limitation is that this does not cover child components of i18n messages as that was more complicated than I wanted to get into right now.
2026-04-14 18:35:51 +03:00
Alex Rickabaugh f9f24fc669 feat(forms): shim legacy NG_VALIDATORS into parseErrors for CVA mode (#67943)
- Injected `NG_VALIDATORS` into `FormField` and exposed it via an internal getter.
- Created a `computed` signal in `cvaControlCreate` to run legacy validators and map into standard validation errors without generic `as any` type assertions.
- Intercepted `registerOnValidatorChange` to trigger updates even when the model value remains unchanged (e.g., going from `null` to `null`).
- Added integration tests to verify parse error propagation and reactivity.

PR Close #67943
2026-04-14 18:32:24 +03:00
Alex Rickabaugh 72d3ace03c fix(forms): use controlValue in NgControl for CVA interop (#67943)
use controlValue() instead of value() to ensure that CVA controls see the most recent user input immediately rather than waiting for it to be synchronized after debouncing

PR Close #67943
2026-04-14 18:32:24 +03:00
Kam c8e23d3a9d fix(docs-infra): prevent inline code wrapping in CLI reference table
Inline code elements inside table cells inherited `width: 100%` from
the global code styles, causing short codes like `s`, `dev` to stack
vertically instead of rendering on the same line. Add `min-width` to
table cells containing code to ensure proper inline layout.
2026-04-14 18:29:10 +03:00
arturovt c90b6b398e fix(router): normalize multiple leading slashes in URL parser
URLs with three or more consecutive leading slashes (e.g. `///test`) were
parsed incorrectly by `DefaultUrlSerializer`. The parser consumed only two
leading slashes, leaving a third that caused `parseSegment()` to produce an
empty `UrlSegment`. When serialized back, that empty segment rendered as
`//test` — a protocol-relative URL that browsers resolve as a different
origin and reject with a `SecurityError` when passed to
`history.pushState`/`replaceState`.

The fix changes `parseRootSegment()` to consume all consecutive leading
slashes instead of just one, normalizing any number of leading slashes to
a single `/` before the path is parsed.

Closes #49610
2026-04-14 12:34:03 +03:00
Andrew Scott c2f4b2af7c refactor(compiler-cli): decouple SymbolReference from AST nodes in template checker
To support the need to resolve symbols without full AST access (e.g. when using virtual files), this commit decouples `ReferenceSymbol` from `ts.ClassDeclaration`.

Changes:
- Updated `ReferenceSymbol.target` to use `SymbolReference` instead of `ts.ClassDeclaration`.
- Removed `getReferenceTargetNode()` from `SymbolDirectiveMeta` and transitioned to `getSymbolReference()`.
- Refactored `getTsSymbolOfReference` in `checker.ts` to handle `SymbolReference` and resolve it to a `ts.Symbol` using a position-optimized AST traversal. This avoids using the private `getTokenAtPosition` API and avoids full file scans by only traversing nodes containing the target position.
2026-04-14 12:32:48 +03:00
Jaime Burgos 2f5ab541ea feat(core): enhance profiling with documentation URLs
Enhances the Chrome DevTools performance profiling integration by adding links to relevant Angular documentation for lifecycle hooks and profiler events.
2026-04-13 22:37:11 +03:00
Matthieu Riegler f9b74e90e3 refactor(core): simplifying the ComponentFactory usage
The `ComponentFactory` has been removed from the public API in #68055.
This commit continues the cleanup and also removes `ModuleWithComponentFactories` from the public API.
2026-04-13 22:24:18 +03:00
Matthieu Riegler 1fa8bb7a99 refactor(vscode-extension): allow toggle attributes via LS.
This change allows to toggle attributes that are on their own line and have a 1+ leading space.

This change doesn't suffer from the issue that was reverted in #68067.

Also this change fixes another regression that messed up highlighting if an attribute value included a '//', like in an href.
2026-04-13 22:10:16 +03:00
AleksanderBodurri cb19c69ea6 docs(devtools): create router tree documentation 2026-04-13 21:16:02 +03:00
Michael Small bb03878ae0 docs: add "Using Agent Skills" + command to skills README.md 2026-04-13 21:12:25 +03:00
Ben Hong c879cecb45 docs: add new signal forms cross field logic guide 2026-04-13 21:07:46 +03:00
Jessica Janiuk eb2b06f3d9 docs: draft PR spam policy addendum
This updates the spam policy to be clear about draft pull requests with regards to the 3 PR limit
2026-04-13 20:54:23 +03:00
aparziale 6a435658e2 feat(migrations): Disabling nullishCoalescingNotNullable & optionalChainNotNullable on ng update
Related to angular#67959 disabling two diagnostics errors by `ng update`:

- nullishCoalescingNotNullable
- optionalChainNotNullable
2026-04-13 19:00:21 +03:00
SkyZeroZx 0454d4ced7 refactor(core): deprecate withIncrementalHydration
Deprecates `withIncrementalHydration()` as it is no longer required.

Updates API docs and runtime errors to reflect the new default and guide opt-out.
2026-04-13 18:53:21 +03:00
YooLCD 39e382a756 fix(http): add CSP nonce support to JsonpClientBackend
Add support for CSP nonces in JsonpClientBackend by injecting the CSP_NONCE token.
This ensures that dynamically created script tags for JSONP requests include the
required nonce attribute to comply with strict Content Security Policies.
2026-04-13 16:01:11 +03:00
Matthieu Riegler df9eed4ff1 refactor(core): remove ComponentFactoryResolver usages
This API was deprecated for a longtime, and was remove by #68055 from the public API.

We do have alternatives to this old API, so we can entirely remove it to spare some bytes
2026-04-13 16:00:03 +03:00
Angular Robot 43ba6b6047 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-13 15:22:58 +03:00
Doug Parker 8ce9cc4f6b feat(core): register AI runtime debugging tools
This registers AI runtime debugging tools during platform creation and unregisters them when the platform is destroyed. This roughly matches existing usage of global utils with respect to timing. It is limited to dev mode only because these tools are exclusively for debugging Angular's internals and not something production users would leverage.
2026-04-13 14:12:48 +03:00
Doug Parker 0c1cc6a89d refactor(core): add registerAiTools function
This will centrally manage all the AI tools supported by Angular out of the box.
2026-04-13 14:12:48 +03:00
Doug Parker 5f5428dfc0 refactor(core): implement Angular signal graph tool
This provides an `angular:signal_graph` in-page tool which exposes the signal graph from the component rendered for a particular DOM element. It leverages the algorithm defined for Angular DevTools, which essentially means it takes the effects registered on the components injector and walks transitive dependencies to find all signals referenced by the component in an effect or the template.
2026-04-13 14:12:48 +03:00
Doug Parker 06c0faecb1 refactor(core): define tool interfaces for AI agents
These serve as the type definitions for interacting with the `chrome-devtools-mcp` AI runtime debugging functionality. Eventually this will hopefully be upstreamed to some more authoritative location, but for now this will do.
2026-04-13 14:12:48 +03:00
Doug Parker cf47eb41ff test: use strict mode for ng_elements integration test
Apparently the Rollup bundle for these tests defaults to `es` format, meaning it expects to be loaded at runtime as native ESM. This was not happening because it was loaded as a regular `<script src="...">` tag (note the lack of `type="module"`).

This is problematic because Rollup assumed it would be running in a scoped environment, meaning [this function](https://github.com/angular/angular/blob/adb8d1078d5f127085952ca81951c18e0178a038/packages/core/primitives/event-dispatch/src/event.ts#L45), which happens to be named `addEventListener` but does *not* implement the `EventTarget.prototype.addEventListener` contract, was being bundled as a simple:

```javascript
function addEventListener(element, ...) {
  // ...
}
```

Since this was loaded with no `type="module"` or `'use strict';`, the script executed in "sloppy mode", meaning all `var` statements and function definitions are implicitly global. Since `window` *is* the `globalThis` object, this random `addEventListener` function clobbers the actual `window.addEventListener` and breaks any calls to it because they're not implementing the same contract.

Fix is to just use `<script src="..." type="module">`. Alternatively we could bundle in an IIFE, which Rollup does support, but in theory we could depend on external ES modules which aren't bundled, so the `type="module"` seems a little safer and more future-proof.
2026-04-13 14:12:48 +03:00
Doug Parker 0f6e850a65 test(router): remove addEventListener call count check
Creating a platform and bootstrapping an application might register more events than just what the router expects (and an event will be added to platform creation in this PR). This test shouldn't be so strict about it.
2026-04-13 14:12:48 +03:00
Matthieu Riegler 70368ea94d refactor(http): Make BrowserXhr/XhrFactory tree-shakable
3bc095d made the `FetchBackend` the default, we shouldn't load anything Xhr related by default anymroe.
2026-04-13 13:56:03 +03:00
Jessica Janiuk 3c7641151c fix(core): escape forward slashes in transfer state to prevent crawler indexing
This commit escapes forward slashes in the transfer state JSON output as \u002F to prevent search engine crawlers from aggressively indexing relative paths inside the inline script tag. It also updates related unit and integration tests across core and platform-server.

Fixes #65310
2026-04-13 13:54:55 +03:00
kirjs f25c7ce6a6 docs(forms): update signal forms migration guide 2026-04-13 13:25:37 +03:00
Angular Robot 5f74e7ec57 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-13 11:33:31 +03:00
aparziale 973ede6ccc refactor: Mobile layout api reference
Fix mobile layout shift in API reference

fix #67650
2026-04-13 11:24:39 +03:00
Michael Small 59513b740d docs: add dev-app section to contributing docs
docs: link directly to dev-app `README.md`
2026-04-13 11:18:27 +03:00
Andrew Scott 1ca9d28ea5 refactor: remove all deep imports in language service
Removes all deep imports, which cause problems with vitest module resolution
2026-04-13 11:16:26 +03:00
Kam c3d4be4a61 docs(docs-infra): fix card container overflow on mobile viewports
Override h2 min-width in docs-card-container-header for small screens
and add docs-content container query fallback to hide SVG illustrations.
2026-04-13 11:09:46 +03:00
Kristiyan Kostadinov e5f96c2d88 fix(compiler-cli): animation events not type checked properly when bound through HostListener decorator
Fixes that we weren't inferring the type of `animate.` event correctly, if they're bound through a `@HostListener` decorator.
2026-04-13 11:05:16 +03:00
Kristiyan Kostadinov 65bf054ee4 refactor(compiler-cli): fix typo
Fixes a typo in the name of `OutOfBandDiagnosticCategory`.
2026-04-13 11:05:16 +03:00
Kam b5b8631198 docs(docs-infra): consolidate tab menu margins for phone breakpoint
Replace separate margin-left/margin-right overrides with a single
margin shorthand in the phone-only media query, aligning spacing
with the base rule and preventing edge collision on small screens.
2026-04-13 11:01:39 +03:00
Kam fda8d201bb docs(docs-infra): fix essentials next-step navigation pills
Update the "Next step" pill in templates to point to signal-forms
instead of skipping it, and add a next-step pill in signal-forms
linking to dependency-injection.
2026-04-13 10:50:55 +03:00
Kam e8eb179477 docs(docs-infra): add external links to W3C specs in Angular Aria overview
Link "W3C Accessibility Guidelines" to WCAG 2.2 and "WAI-ARIA patterns"
to the W3C APG patterns page, giving readers direct access to the
referenced specifications.
2026-04-13 10:49:51 +03:00
Andrew Scott a89b565395 refactor(language-service): Avoid deep import of comments helper
avoids deep import from compiler-cli that causes issues in some environments
2026-04-10 21:57:54 +03:00
Doug Parker e453848ae6 test(platform-browser): verify that Angular supports bootstrapping under shadow roots
This tests bootstrapping Angular underneath a shadow root and that styles are applied and removed at the correct locations.
2026-04-10 21:44:08 +03:00
Doug Parker cdda51a3b2 feat(core): support bootstrapping Angular applications underneath shadow roots
This is a minimal implmentation which just focuses on registering parent shadow roots in `SharedStylesHost` correctly.

We don't currently reference count usage of host values, meaning that as soon as we call `removeHost`, all styles are removed from it, even if other components relied on them. Therefore there is no good way to know whether styles are still needed or not, leaving us with the choice of either leaking them longer than necessary or destroying them while another component still needs them. The compromise I'm using here is to delete styles when destroying a component under a shadow root (based on the assumption that only one component will exist per shadow root) and to leave styles when destroying a component in the main document (based on the assumption that dialogs being destroyed should not impact the main application).

Neither assumption is totally safe to make, but we're hoping this is a viable balance for the moment. In the future we should look into lifting these restrictions to better support those use cases while properly reference counting usage of hosts in `SharedStylesHost`.

I also added some small tests to confirm that SSR styles are not duplicated, as an earlier implementation accidentally duplicated them. This should ensure we don't repeat that mistake.
2026-04-10 21:44:08 +03:00
Doug Parker e77fb5a125 refactor(core): don't duplicate styles when adding the same host multiple times
This shouldn't have been happening before, but now that we're going to start calling `addHost` during root component boostrap, we may call `addHost` on the same node multiple times and don't want to duplicate styles.
2026-04-10 21:44:08 +03:00
Doug Parker ad04929d8e refactor(core): add getRootNode to RNode interface
This is necessary for an `RNode` to discover whether it is within the context of a shadow root, which is needed to know where a component's style should be placed.

The method is Baseline Widely Available, however we need to treat it as optional for SSR / JSDom contexts where shadow DOM is not supported.
2026-04-10 21:44:08 +03:00
Doug Parker df1f5d4394 refactor(core): move SharedStylesHost interface into @angular/core with a dedicated InjectionToken
This allows code in `@angular/core` to inject and use `SharedStylesHost`, even though the implementation is defined in `@angular/platform-browser`.
2026-04-10 21:44:08 +03:00
aparziale 1415d86980 fix(migrations): Fix typo for strict-template migration
Fix typo for strict-template migration
2026-04-10 20:22:16 +03:00
Alan Agius a268547368 build: update rules_angular setup in MODULE.bazel
Migrate from using use_repo_rule and override_repo directly to using the rules_angular.setup module extension for configuring configurable dependencies.
2026-04-10 20:14:06 +03:00
Kam 843f425ec8 docs(docs-infra): fix homepage nav overlay and banner visibility between 701–900px
The homepage navigation bar rendered with `height: 0` on viewports between
701–900px, causing its content to overflow on top of the announcement banner
and block scrolling. Reset nav height to `auto` at tablet sizes, center the
v21 banner, adjust its top margin, and hide the redundant search field since
the nav bar already provides one.
2026-04-10 17:39:31 +03:00
Angular Robot 90c1542801 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-10 17:34:59 +03:00
Angular Robot 1391b686db docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-10 17:03:40 +03:00
Doug Parker 337e6e7d6e refactor: add flaky tests workflow
I've had some success asking the Antigravity agent to find flaky tests and propose fixes for them, then just running it in the background and reviewing what it finds. Upstreaming this to the repo so others can use it, since it includes helpful notes like `--runs_per_test` and leveraging random seeds as well as an iteration loop.

I opted not to have the agent do anything with PRs just yet, but if this is useful and we build confidence in it, we can explore that in the future.
2026-04-10 16:45:32 +03:00
Angular Robot 7d9b1dd076 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-10 16:41:35 +03:00
arturovt 030422850b docs: add documentation for NG1002
Adds a documentation page for the NG01002 runtime error thrown by
FormGroup and FormArray when setValue is called with a value that is
missing an entry for one or more registered controls.

The error code is also changed from positive (1002) to negative (-1002)
so that Angular appends a link to the error reference page in dev mode,
consistent with how other documented errors (e.g. NG01101, NG01203) are
handled.
2026-04-10 10:54:41 +03:00
Matthew Beck 2c5aabb9da fix(compiler): don't escape dollar sign in literal expression
Removes the escape for `$` in literal expressions. I don't think this is
required with our output.
2026-04-10 09:23:50 +03:00
Jessica Janiuk 836094c072 fix(service-worker): resolve TS 6.0 compatibility for messageerror listener
In standard DOM definitions (lib.webworker.d.ts), the messageerror event
is typed as MessageEvent, which lacks the waitUntil property found on
ExtendableMessageEvent. In modern versions of TypeScript (including TS 6.0),
this causes compile-time overload resolution errors when the listener function
is explicitly typed to expect ExtendableMessageEvent.
2026-04-09 21:46:28 +03:00
Jessica Janiuk 68628dd45b feat(platform-browser): make incremental hydration default behavior
This commit updates provideClientHydration to automatically enable incremental hydration by default. It also introduces a new withNoIncrementalHydration feature for opting out, adds conflict safety checks, and includes a schematic migration.
2026-04-09 18:53:13 +03:00
Matthieu Riegler 47fcbc4704 feat(compiler): allow safe navigation to correctly narrow down nullables
The commit updates the TCB for safe navigation expressions to allow for correct narrowing of nullables.

This will trigger the `nullishCoalescingNotNullable` and `optionalChainNotNullable` diagnostics on exisiting projects.
You might want to disable those 2 diagnotiscs in your `tsconfig` temporarily if you want to update your project without having to fix all the issues at once.

Narrowing can be disabled altogether with `strictSafeNavigationTyes: false`.

fixes #37619

BREAKING CHANGE: This change will trigger the `nullishCoalescingNotNullable` and `optionalChainNotNullable` diagnostics on exisiting projects.
You might want to disable those 2 diagnotiscs in your `tsconfig` temporarily.
2026-04-09 18:26:08 +03:00
Alan Agius b9265cc8ff docs: update typescript version requirement for angular 22
Update the supported TypeScript version range for Angular 22.0.x from `>=5.9.0 <6.0.0` to `>=6.0.0 <6.1.0` to reflect the correct compatibility requirements.
2026-04-09 18:13:53 +03:00
Angular Robot 1a16a40aaa docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-09 16:01:33 +03:00
Angular Robot db9f9a8082 build: update all non-major dependencies
See associated pull request for more information.
2026-04-09 15:41:19 +03:00
Angular Robot 8633f15613 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-04-09 14:13:51 +03:00
Andrew Scott 5516769e17 release: cut the v22.0.0-next.7 release 2026-04-08 12:48:22 -07:00
Andrew Scott f95d75752f docs: release notes for the v21.2.8 release 2026-04-08 12:40:41 -07:00
Doug Parker 51c3a11d69 release: bump Angular DevTools version to 1.14.1 2026-04-08 12:15:55 -07:00
Andrew Scott 6fee6514c2 refactor(compiler-cli): decouple SymbolBuilder from BoundTarget and minimize adapter surface
Decouple `SymbolBuilder` from the full `BoundTarget` interface by introducing a purpose-built `SymbolBoundTarget` interface containing only the 4 methods required for symbol resolution. This eliminates the need for the large, pass-through `BoundTargetAdapter` and further isolates `SymbolBuilder` from compiler-internal implementation details.

Also minimize `TypeCheckableDirectiveMetaAdapter` by redefining `SymbolDirectiveMeta` to not extend `DirectiveMeta`, exposing only the properties actually used by `SymbolBuilder`.

Removed dead code `getDirectiveMeta` in `template_symbol_builder.ts` which was unused.

These changes improve maintainability and ensure a cleaner architecture by strictly defining the boundaries of what `SymbolBuilder` needs from the rest of the system.
By limiting the required inputs to only what's necessary for the implementation, we make it easier to re-use
the implementation between different compiler architectures
2026-04-08 11:33:41 -07:00
N. Coury a24179e125 fix(core): remove obsolete iOS cursor pointer hack in event delegation
Since WebKit commit 67a62d98 (merged for iOS 13), WebKit no longer restricts
click event bubbling to interactable nodes like `div` or `body`. The
`cursor: pointer` hack polyfill is therefore obsolete and can safely be
removed without breaking JSAction behavior.
2026-04-08 11:31:30 -07:00
Angular Robot c7518a4ed6 build: update cross-repo angular dependencies
See associated pull request for more information.

Closes #67980 as a pr takeover
2026-04-08 11:04:49 -07:00
Alan Agius c70b4fec8c docs: fix typos and formatting in spam policy and saved replies
- Enclose the spam saved reply in a code block in `saved-issue-replies.md`
- Correct spelling and punctuation in `saved-issue-replies.md` and `spam.md`
2026-04-08 09:41:22 -07:00
Kam 4739bde9fb docs: fix typos and grammar errors across documentation
Fix various typos, misspellings, and grammar issues across contributing
docs, adev content guides, and agent skills documentation.

- "an minimum" → "a minimum" (CONTRIBUTING.md)
- "GitHub accounts" → "GitHub account" (CONTRIBUTING.md)
- "decendants" → "descendants" (components/styling.md)
- "templates are using" → "templates is using" (hydration.md)
- "A automated" → "An automated" (branches-and-versioning.md)
- "Github" → "GitHub" (branches-and-versioning.md, commit-message-guidelines.md)
- "practices makes" → "practice makes" (caretaking.md)
- "corresponds" → "correspond" (triage-and-labelling.md)
- "one a line" → "a line" (documentation-authoring.md)
- "straight forward" → "straightforward" (using-fixup-commits.md)
- "or you decide" → "or you can decide" (anatomy-of-components.md)
- "whenver" → "whenever" (angular-new-app/SKILL.md)
2026-04-08 09:40:47 -07:00
Angular Robot b16a8a32d8 build: update dependency marked to v18
See associated pull request for more information.
2026-04-08 09:40:25 -07:00
Andrew Scott 30c950f133 refactor(compiler-cli): Fix regressions caused by ts.typechecker removal
removing ts.typechecker in a prior refactor caused some regressions, particularly when multiple directives
appear on a single elemnt. this is now addressed by using an id for directives and storing that in the tcb comment
2026-04-08 08:14:44 -07:00
Matthieu Riegler e95d84684f fix(vscode-extension): restore correct highlighting
This is a regression introduced by #66891 when trying to support commenting attribute via the language service extension
2026-04-07 14:53:08 -07:00
Alex Rickabaugh de56d74da3 fix(forms): align FormField CVA selection priority with standard forms
Prioritize custom ControlValueAccessor instances over default or built-in accessors when applying the [formField] directive. This is achieved by directly consuming selectValueAccessor from @angular/forms, ensuring absolute alignment with the precedence rules used across standard Angular form directives.
2026-04-07 14:21:44 -07:00
Alex Rickabaugh 2e9aeea0fe fix(forms): deduplicate writeValue calls in CVA interop
Update bindings['controlValue'] during onChange to track the view value. This allows bindingUpdated to skip writeValue if the model value matches the last seen view value, preventing redundant writes.

Fixes #67847
2026-04-07 14:21:44 -07:00
Matthieu Riegler a0aa8304cd feat(core): bootstrap via ApplicationRef with config
This is to align the shape of the method with `createComponent`

BREAKING CHANGE:The second arguement of appRef.bootstrap does not accept `any` anymore. Make sure the element you pass is not nullable.

fixes #67946
2026-04-07 12:48:53 -07:00
splincode 77f1ca08e4 fix(core): handle missing serialized container hydration data
Simplify the hydration regression test by removing conditional early-return branches and relying on direct Jasmine expectations while keeping strict typing and OnPush configuration.
2026-04-07 11:22:03 -07:00
Angular Robot 2ff9db30e0 build: lock file maintenance
See associated pull request for more information.
2026-04-07 10:48:02 -07:00
Angular Robot 490be7a13d docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-04-07 10:46:18 -07:00
Kam 1c9c4536d6 docs(docs-infra): fix v21 event video not responsive on mobile
Replace raw iframe with docs-video component to fix YouTube embed
overflowing on mobile viewports.
2026-04-07 09:47:50 -07:00
Stephen Fluin 64b52c1a30 docs(docs-infra): warning about upgrading to v21 2026-04-07 09:47:13 -07:00
Kam 8132a96884 docs(docs-infra): preserve navigation origin when clicking cross-category links
When a sidebar item links to a page in a different category (e.g., Route
transition animations under Animations links to a Routing page), clicking
back navigates to the main menu instead of the originating category.

Store the originating category in NavigationState when clicking a
cross-referenced item, so the back button returns to the correct section.
2026-04-07 09:46:18 -07:00
Matthieu Riegler b48603eab0 build: remove undici
Node provides now its own fetch implementation, so we can remove undici from our dependencies and use the built-in one instead.
2026-04-07 09:45:32 -07:00
Andrew Scott b9cbb147d9 refactor(compiler-cli): Export SymbolKind for external use
exports SymbolKind for use outside of angular monorepo
2026-04-07 09:44:09 -07:00
Cameron Smick 236d6d4946 refactor(devtools): pass node to logValue to log the appropriate prop to the console
The "Log to console" button in the prop-actions-menu component incorrectly logs the entire props object rather than the value of the individual prop with which the button is associated. Passing the `node` to the logValue function fixes the prop lookup logic and logs the appropriate prop value to the console.
2026-04-07 09:35:12 -07:00
Doug Parker 19ce90fe9b docs: add spam policy
This defines an initial policy with regard to issue / PR spam as well as a saved reply for bulk-closing large issue / PR counts at once.
2026-04-07 09:32:15 -07:00
Matthieu Riegler b1f5181ffd 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 `createComponent` function.
2026-04-07 09:30:25 -07:00
Kristiyan Kostadinov ab061a7610 fix(compiler-cli): error for type parameter declarations
Fixes an error that was heppning when a generic param has type parameters of its own. There were a few different issues going on:
1. In #67707 I had changed a bit how we pass the `genericContextBehavior` which ended up ignoring the `useContextGenericType` option from the environment.
2. All directives depend on themselves, but we were overridding the `genericContextBehavior` for the directive being processed.
3. The type translator wasn't handling type parameter declarations. Technically we shouldn't be able to hit a code path that has a type parameter, however it's also easy enough to handle so we might as well.

Relates to #67704.
2026-04-07 09:29:29 -07:00
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
Alan Agius e84e35cdd6 fix(core): prevent binding unsafe attributes on SVG animation elements (#67797)
SVG animation elements (`animate` and `set`) can be used to animate sensitive attributes like `href` or `xlink:href`. Binding to these animation attributes (like `to`, `from`, or `values`) with a sensitive target creates an XSS vector.

This change mitigates this risk by:
1. Classifying `to`, `from`, and `values` on `<animate>` and `<set>` elements as `ATTRIBUTE_NO_BINDING` in the DOM security schema to prevent standard dynamic bindings.
2. Adding runtime validations in `ɵɵvalidateAttribute` to verify that `attributeName` is not a sensitive attribute (such as `href` or `xlink:href`) when processed by a set of `SECURITY_SENSITIVE_ATTRIBUTE_NAMES`. If it is, a runtime error `UNSAFE_ATTRIBUTE_BINDING` is thrown.
3. Adding regression tests in `integration_spec.ts` to ensure unsafe bindings throw an error while safe ones pass correctly.

PR Close #67797
2026-04-01 11:43:58 +02:00
Alan Agius 028e1d3ce0 fix(core): treat object[data] as resource URL context (#67797)
Previously, the `data` attribute of the `<object>` tag was being sanitized as a regular URL instead of a `ResourceURL`, which is security-sensitive.
This commit updates the runtime sanitization logic to correctly identify `object[data]` as a `ResourceURL` context. Additionally, the sanitizer lookup logic has been refactored to use a more efficient lookup map (`RESOURCE_MAP`) instead of multiple `Set` lookups, providing better performance and maintainability.

Added tests to verify the correct sanitization of `object[data]` and its behavior with trusted values.

PR Close #67797
2026-04-01 11:43:58 +02:00
Alan Agius 08d36599d7 fix(compiler): register SVG animation attributes in URL security context (#67797)
This change is a security hardening measure to prevent potentially unsafe attribute value manipulation through SVG animations. By mapping `animate|to`, `animate|from`, `animate|values`, and `set|to` to the `SecurityContext.URL`,  Angular will now automatically sanitize these attributes.

PR Close #67797
2026-04-01 11:43:58 +02:00
Kam f257f54967 docs(docs-infra): improve angular-new-app skill
Consolidate duplicate persona intro, add commonly useful ng new flags
and missing generators to scaffolding guidelines.
2026-04-01 09:26:35 +02:00
tomer953 8fa6617352 fix(core): resolve component import by exact specifier in route lazy-loading schematic
Avoid substring matching on importClause.getText() which caused suffix collisions (e.g., BarComponent vs FooBarComponent). Use AST-based matching for default and named (including aliased) imports to reliably resolve the correct import path when generating loadComponent.
2026-04-01 09:24:08 +02:00
Doug Parker 7ba8929504 test: fix flakiness in image-directive e2e tests
Fixes race conditions where intermediate layout renders caused the browser to emit 'largest-contentful-paint' events or 'load' events that led to inconsistent console logs. Updated tests to correctly wait for elements to stabilize and properly filter expected log messages.
2026-04-01 08:40:42 +02:00
Kam ef7679b7a5 refactor(forms): use strict equality for pending status getter
The `pending` getter in `AbstractControl` used loose equality (`==`)
while all other status getters (`valid`, `invalid`, `disabled`) use
strict equality (`===`). Both sides are strings so behavior is
identical, but this inconsistency would fail strict linting rules.
2026-03-31 13:51:55 +02:00
Angular Robot 277f9adb74 build: lock file maintenance
See associated pull request for more information.
2026-03-31 13:41:22 +02:00
Angular Robot daa372421b build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-31 12:01:19 +02:00
Alan Agius 1a6785874e docs: modernize CLI reference for build and test
Updates the Angular CLI reference to reflect current framework defaults:
- Changes the recommended application builder to @angular/build:application.
- Replaces Jasmine and Web Test Runner with Vitest as test runner examples.
2026-03-31 11:56:02 +02:00
Angular Robot c9502999cf build: update pnpm to v10.33.0
See associated pull request for more information.
2026-03-30 12:45:23 +02:00
Matthieu Riegler 0f960a5514 docs(docs-infra): sanitize markdown tooltip in Code editor 2026-03-30 12:16:11 +02:00
Alan Agius 7871093822 fix(localize): validate locale in getOutputPathFn to prevent path traversal
The `localize-translate` CLI tool uses the `locale` field from translation files to expand the `{{LOCALE}}` placeholder in the output directory. It failed to sanitize `locale` input, allowing malicious translations to write files outside of the configured output directory.

This change mitigates this issue by combining.

Closes #67906
2026-03-30 12:15:26 +02:00
hawkgs 687e75c42a refactor(devtools): update directive forest chevrons positioning method
Update how chevrons of each expandable directive forest item are positioned by being more explicit.
2026-03-30 12:14:18 +02:00
Angular Robot 60930f847e build: update all non-major dependencies
See associated pull request for more information.
2026-03-30 11:15:50 +02:00
SkyZeroZx 713eca74e7 docs: update signal form tutorial 2026-03-30 11:11:22 +02:00
SkyZeroZx c6f73f4127 docs: update url from <base href> 2026-03-30 10:44:07 +02:00
Shuaib Hasan Akib 95fff0ee98 docs: align list formatting and improve emphasis
Aligns list formatting, replaces the “Helpful” block with an
IMPORTANT note for better visibility, and removes the separate
example file by inlining the single relevant line directly
in the documentation.
2026-03-30 10:35:44 +02:00
marktechson 86bbc9474c docs: add agent skills documentation and new readme 2026-03-27 11:39:44 -07:00
Georgi Serev 9d79ec6866 docs(docs-infra): introduce a custom UrlSerializer
The custom serializer should handle Adev-specific behavior like decoding encoded forward slash similarly to the app host.
2026-03-27 17:17:50 +01:00
Andrei Chmelev fcd0bb0db8 fix(compiler-cli): prevent recursive scope checks for invalid NgModule imports
Avoid recursive local scope lookups when invalid NgModule imports create import cycles.
2026-03-27 16:10:01 +01:00
Matthieu Riegler 12b3a1a755 refactor(migrations): keep the http-xhr-backend migration idempotent
Our migrations should be idempotent in case they are run multiple times.
2026-03-27 15:58:46 +01:00
Kristiyan Kostadinov d1c1bc3200 refactor(compiler-cli): decouple schema checker from typescript
Makes the `DomSchemaChecker` from TypeScript APIs.
2026-03-27 15:58:12 +01:00
aparziale 682aaf943f feat(migrations): add strictTemplates to tsconfig during ng update
Add the strictTemplates option to tsconfig.json with a default value of false
2026-03-27 15:57:09 +01:00
SkyZeroZx 43ef7171b3 docs: update change detection strategy references 2026-03-27 15:43:43 +01:00
Andrew Scott c1261b02db refactor: extract comments utilities to private
allows comments utils to be used in other language service packages
2026-03-27 15:36:37 +01:00
Angular Robot 9aa315cb96 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-27 14:14:02 +01:00
Angular Robot ae28109f5d build: update all github actions
See associated pull request for more information.
2026-03-27 14:03:10 +01:00
Angular Robot 34e1d49b75 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-27 14:01:21 +01:00
SkyZeroZx ff2ba7c864 docs(docs-infra): replace wait with debounce for search
Replaces custom search debounce with `debounced`
2026-03-27 13:57:15 +01:00
Andrew Scott 7234432715 refactor(language-service): Update getTcbNodesOfTemplateAtPosition to be usable without compiler (#67898)
updates getTcbNodesOfTemplateAtPosition to be usable without ngCompiler instance
so it can be shared with more compiler types

PR Close #67898
2026-03-26 21:32:19 +00:00
Andrew Scott fb347afb99 refactor: fix types extraction for private (#67898)
fixes types extraction for private entrypoint of language service

PR Close #67898
2026-03-26 21:32:19 +00:00
Alan Agius d268df6c95 build: remove unused @nginfra/angular-linking dependency
This dependency is not used in this repo.
2026-03-26 18:37:33 +01:00
Doug Parker 61ee183fa7 test: construct local Date objects to fix timezone flakiness
Replaced testing constructions of `Date` objects from `formatDate` tests from plain ISO strings over to 'new Date(year, month, date)'.

Instantiating 'new Date("2024-01-01")' parses the string strictly as UTC midnight ("2024-01-01T00:00:00.000Z"). When local operations execute (such as calculating `getThursdayThisIsoWeek` boundaries), the UTC date shifts relative to the executing machine's timezone. For example, in PST (GMT-8), that date translates exactly to 'December 31st 16:00:00', pushing week boundaries backwards.

By wrapping date constructs explicitly as 'new Date(2024, 0, 1)', it natively guarantees local midnight execution and prevents boundaries shifting on global CI Remote Build Execution (RBE) workers.

Example (from a machine in PST):

```javascript
> new Date('2024-01-01')
Sun Dec 31 2023 16:00:00 GMT-0800 (Pacific Standard Time)
> new Date(2024, 0, 1)
Mon Jan 01 2024 00:00:00 GMT-0800 (Pacific Standard Time)
```
2026-03-26 18:34:08 +01:00
Doug Parker a1385ad977 test: remove unsupported timezone from formatDate tests
Removes the 'America/New_York' timezone string test case from `formatDate` tests because the underlying `Date.parse` API does not support IANA timezone strings. This caused the timezone calculation to silently fall back to the local executing machine's timezone, leading to non-deterministic test flakiness on Remote Build Execution (RBE) workers operating in varying geographic locations.
2026-03-26 18:34:08 +01:00
SkyZeroZx ecc616b94b docs: fix indentation that breaks roadmap rendering 2026-03-26 18:33:01 +01:00
cexbrayat 9bb1e78969 docs: remove private utils from testing skills 2026-03-26 18:29:17 +01:00
Jessica Janiuk b82901f8f9 fix(dev-infra): improve PR review skill handling of git worktrees
The current PR review skill blindly attempts to checkout branches using the `gh` CLI.
This creates fatal errors if the branch being checked out is already tied to a different git worktree.
Additionally, the logic didn't give the user a clear way to enforce a remote code review when they are the author.

This change updates the `Execution Workflow` to prioritize an explicit user instruction to review remotely, and updates the `Local Code Review` instructions to enforce checking for worktree conflicts before executing local checkouts.
2026-03-26 17:49:28 +01:00
Leon Senft d4c085d2cc release: cut the v22.0.0-next.5 release 2026-03-25 16:04:32 -07:00
Leon Senft f187d23923 docs: release notes for the v21.2.6 release 2026-03-25 15:43:59 -07:00
Alex Rickabaugh 24e52d450d feat(forms): add debounce option to validateAsync and validateHttp
This adds support for a `debounce` option to the `validateAsync` and `validateHttp` functions.
This allows developers to debounce the triggering of async validators to improve performance.

A `DebounceTimer` type was also added to `@angular/core` to represent the wait condition parameters uniformly.
2026-03-25 14:17:52 -07:00
Leon Senft b5af15a332 test(forms): support directive composition with FormField
Support composing the `FormField` directive with custom controls:
2026-03-25 13:35:02 -07:00
Angular Robot 0007723a03 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-25 13:32:59 -07:00
Alan Agius b40d11eec4 build: consolidate domino bundling in platform-server
Move the domino bundling logic and related shims into a centralized third_party directory within packages/platform-server. This avoids duplication of the bundling logic and ensures consistent shimming across the platform-server package and its entry points.

Following a conversation with OSS licensing, this change also includes the domino LICENSE file in the generated npm package to comply with licensing requirements for bundled third-party code.

```
├── fesm2022
│   ├── init.mjs
│   ├── init.mjs.map
│   ├── platform-server.mjs
│   ├── platform-server.mjs.map
│   ├── _server-chunk.mjs
│   ├── _server-chunk.mjs.map
│   ├── testing.mjs
│   └── testing.mjs.map
├── LICENSE
├── package.json
├── README.md
├── third_party
│   └── domino
│       ├── bundled-domino.d.ts
│       ├── bundled-domino.mjs
│       ├── bundled-domino.mjs.map
│       └── LICENSE
└── types
    ├── init.d.ts
    ├── platform-server.d.ts
    └── testing.d.ts
```
2026-03-25 13:31:05 -07:00
Andrew Scott eecfa4c909 refactor(language-service): Export template target from API
allows template target to be used in other tooling
2026-03-25 13:07:42 -07:00
Michael Small 89629d8ac1 docs(forms): replace rxResource request w/ params 2026-03-25 13:04:52 -07:00
Matthieu Riegler cf3b7fe489 refactor(core): remove todo
This TODO hinted that we also needed to remove a g3 patch.
2026-03-25 13:02:23 -07:00
Alex Rickabaugh 16adbbf423 fix(core): ensure custom controls resolve transitive host directives
Custom controls can be modeled using a set of host directives to alias
and expose value and valueChange (or checked/checkedChange) bindings,
as well as native attributes like disabled.

This commit updates initializeCustomControlStatus to correctly identify
host components using mapped inputs/outputs, even when those inputs are
exposed via transitive host directives. It also updates
customControlHasInput so that the custom control presence check correctly
evaluates the exposed inputs across all applied host directives, caching
the result to optimize performance on hot code paths.
2026-03-25 13:00:46 -07:00
Kristiyan Kostadinov 3382e8a34b refactor(compiler-cli): generalize out of band diagnostics recorder
Currently the `OutOfBandDiagnosticRecorder` is tied to producing TypeScript diagnostics, however some of our use cases might call for a different form.

These changes decouple the recorder from TypeScript and make the diagnostic type generic.
2026-03-25 12:59:11 -07:00
Matthieu Riegler 1938054f34 docs(docs-infra): remove explicit OnPush 2026-03-25 12:58:39 -07:00
hawkgs 0ad18ee933 refactor(devtools): drop explicit OnPush change detection strategy
Drop explicit `ChangeDetectionStrategy.OnPush` from the apps since it's now the default.
2026-03-25 12:58:11 -07:00
Kristiyan Kostadinov 9ee4f83705 build: update to TypeScript 6 stable
Updates the repo to the stable version of TypeScript 6.
2026-03-25 12:57:49 -07:00
Angular Robot 5565ff15ae build: update dependency node to v22.22.2
See associated pull request for more information.
2026-03-25 12:57:20 -07:00
Alan Agius 6f20fb513c docs: reword allowedHosts security warning
Update the allowedHosts security warning in the security guide to remove the mention of DNS rebinding, which is primarily relevant for the dev server, and refocus on host header injection and SSRF. Additionally, clarify that allowing all hosts with "*" is only appropriate when header validation is handled by an external layer.
2026-03-25 12:56:42 -07:00
Alan Agius ad57c9d0d4 build: re-sync file
This fixes main CI
2026-03-25 09:31:58 +01:00
Matthieu Riegler eae8f7e30b feat(core): Set default Component changeDetection strategy to OnPush
The default change detection strategy is now OnPush.

BREAKING CHANGE: Component with undefined `changeDetection` property are now `OnPush` by default. Specify `changeDetection: ChangeDetectionStrategy.Eager` to keep the previous behavior.
2026-03-24 16:25:02 -07:00
guidettj 050b14bd7f docs: fix incorrect getHarnesses() method to getAllHarnesses and broken link 2026-03-24 15:35:32 -07:00
SkyZeroZx 098553bfe4 docs: update defer section to Markdown and fix absolute URL to relative in adev 2026-03-24 15:34:57 -07:00
Kristiyan Kostadinov d9712e605e refactor(core): expand input flags type
Expands the type for the input flags in definitions since the current one prevents some of the generated code from compiling.
2026-03-24 15:18:28 -07:00
hawkgs 78c2d0aa19 docs(docs-infra): redefine /guide/pipes redirect
Update the definition of the `/guide/pipes` redirect in order to avoid breaking the `a.dev/guide` redirect to Not Found page.
2026-03-24 15:17:11 -07:00
Fausto Davila c9f7a7f649 docs: fix typo in end-to-end.md regarding e2e command 2026-03-24 15:15:10 -07:00
Jens Kuehlers b4ae9cf040 docs: update release date to not clash with Google I/O 2026 2026-03-24 15:14:34 -07:00
Angular Robot 9192dfede1 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-24 15:12:28 -07:00
Angular Robot 1533242577 build: lock file maintenance
See associated pull request for more information.
2026-03-24 15:08:28 -07:00
Alex Rickabaugh 709f5a390c feat(forms): add FieldState.getError()
Added a `getError(kind: string)` method to `FieldState` that returns the first validation error of a given kind, or `undefined` if no such error exists. This method is reactive and will re-evaluate when errors change.

Fixes #63905

Also updated public API goldens and added unit tests.
2026-03-24 15:07:55 -07:00
Alex Rickabaugh ee8d2098cb fix(forms): change FieldState optional properties to non-optional | undefined
This improves compatibility with TypeScript's exactOptionalPropertyTypes.

Fixes #67246
2026-03-24 14:51:31 -07:00
weedorflow 37b1c5d0fe docs: clarify size budget configuration 2026-03-24 14:49:34 -07:00
SkyZeroZx 5879f310b4 docs: Update docs with ComponentInputBindingOptions 2026-03-24 14:48:52 -07:00
SkyZeroZx 1782114862 refactor(router): expose ComponentInputBindingOptions in public API
Expose  `ComponentInputBindingOptions` as part of the public API
2026-03-24 14:48:52 -07:00
Matthieu Riegler 8bc31a515f feat(core): Allow other expression for exhaustive typechecking
When the switched expression is nested within a union, exhaustive typechecking needs to know which expression to check.
This change adds the possibility of specifying the expression to check:

```
@Component({
  selector: 'app-root',
  imports: [],
  template: `
    @switch (state.mode) {
      @case ('show') { {{ state.menu }}; }
      @case ('hide') {}
      @default never(state);
    }
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {
  state!: { mode: 'hide' } | { mode: 'show'; menu: number };;
}
```

fixes #67406
2026-03-24 14:42:28 -07:00
Leon Senft 0eeb1b5f03 fix(forms): allow FormRoot to be used without submission options (#67727)
The `[formRoot]` directive will no longer call `submit()` if the bound
form doesn't define its own submission options. This allows the
directive to be used solely for the default behavior it provides:
setting `novalidate` on the `<form>` and calling `preventDefault()` on
the `submit` event.

Fix #67367

PR Close #67727
2026-03-23 15:41:19 -07:00
Leon Senft f4a5b42ebe refactor(forms): rename directive files for consistency (#67727)
- **FormField**:  `form_field_directive.ts` -> `form_field.ts`
- **FormRoot**:   `ng_signal_form.ts`       -> `form_root.ts`

PR Close #67727
2026-03-23 15:41:19 -07:00
Aleksander Bodurri 36edf4870f fix(devtools): fix incorrect logic in destroy function for ChromeMessageBus
Destroy uses window.removeEventListener but the ChromeMessageBus doesn't actually depend on a window object.

In practice this code is unlikely to ever be reached. If a tab is closed the entire context script JS process is killed so this is not an bug that would be very common or even reachable. That being said for correctness this should not be using window.
2026-03-23 14:51:27 -07:00
Joey Perrott 543753f551 ci: correct capitalization of MarkTechson in pullapprove
Correct the capitalization of MarkTechson's username to match their GitHub profile, ensuring proper evaluation by PullApprove.
2026-03-23 14:50:19 -07:00
Alan Agius b89af3c8da docs: remove redundant ng command from npx instructions in Angular Developer skill 2026-03-23 14:49:26 -07:00
SkyZeroZx 946f4eacfe docs(docs-infra): remove redundant provide http and zoneless providers
Removes `provideHttpClient(withFetch())` and `provideZonelessChangeDetection()` from the root config since both are already provided by default
2026-03-23 14:48:02 -07:00
SkyZeroZx 26afb736b7 docs: Update provideZonelessChangeDetection tsdocs 2026-03-23 14:48:02 -07:00
Matthieu Riegler f46e8bd440 refactor(compiler): remove fullTemplateTypeCheck compiler option.
The option was deprecated back in v13. Users should use `strictTemplates: true`.
2026-03-23 11:33:15 -07:00
Modeste ASSIONGBON 2615f35da9 docs: fix js doc of signal forms ignoreValidators option. 2026-03-23 11:21:16 -07:00
SkyZeroZx 1f9a42bb42 refactor(http): Make Fetch API the default in HttpBackend
Updates the `HttpBackend` default provider to `FetchBackend`.

Also updates related warning messages to reflect the new default behavior.
2026-03-23 11:20:39 -07:00
Pushkar-Mahajan4 1128e78913 docs: fix typo in Input decorator 2026-03-23 11:19:46 -07:00
Kristiyan Kostadinov 63ac1bd2fd refactor(compiler-cli): decouple host element creation logic from TypeScript
Reworks the logic for constructing a `HostElement` node so that we can reuse it without depending on TypeScript APIs.
2026-03-23 11:16:39 -07:00
SkyZeroZx 6d2eed61a1 docs(docs-infra): fix aria-label parsing breaking headings
Strip all HTML tags and escape quotes in aria-label to avoid breakage
2026-03-23 10:33:15 -07:00
splincode 25dad82e43 refactor(devtools): improve test descriptions by fixing spelling
Fixed misspellings in test descriptions in devtools/projects/shell-browser/src/app/tab_manager_spec.ts: recieved/recieves → received/receives in three it(...) titles.
2026-03-23 10:32:39 -07:00
splincode 13c198ae63 docs: fix typos in ssr-benchmarks README.md
Corrected typos in modules/ssr-benchmarks/README.md: mesure→measure, Struture→Structure, render→renders, benckmark→benchmark, capitalized DevTools, and clarified the flame chart instruction.
2026-03-23 10:27:38 -07:00
SkyZeroZx ad3991cd0b docs(docs-infra): replace non-interactive buttons with spans
These elements are not interactive, so using <button> is misleading for accessibility
(screen readers and keyboard navigation expect an action).
2026-03-23 10:24:08 -07:00
Alan Agius 293ac66a9f ci: support publishing dev-skills to snapshot repository
Updates the snapshot publishing script to package the contents of
`skills/dev-skills` and publish them to the `angular/skills`
repository.

The changes include:
- Ensuring the script always runs from the repository root.
- Updating `publishRepo` to support an optional third argument for
  specifying a custom repository name (defaulting to `-builds`).
- Implementing `publishDevSkills` to package individual skills at the
  root of the snapshot repository.
2026-03-23 09:49:11 -07:00
Matthieu Riegler d2054c7c1a refactor: prepare for required changeDetection prop on G3.
We'll make this a G3 only change to prevent backsliding during the transition period.
2026-03-20 15:52:38 -07:00
Angular Robot eb5bb93195 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-20 15:46:34 -07:00
Angular Robot 621c9083de build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-20 15:22:17 -07:00
splincode c5da47f63f refactor: replace any with stricter types in common and core
- `JsonPipe.transform`: `any` → `unknown`
- `renderStringify`: `any` → `unknown`
- `NgLocalization.getPluralCategory`: `any` → `number`
2026-03-20 15:20:43 -07:00
Kristiyan Kostadinov 96be4f429b fix(compiler): abstract emitter producing incorrect code for dynamic imports
Fixes that the abstract emitter wasn't adding quotes around the URL of a dynamic import.
2026-03-20 15:18:29 -07:00
Kristiyan Kostadinov 5e99ae9f00 fix(core): widen type for directive inputs/outputs
Currently the directive inputs and outputs are typed to match the members of the class. We can't guarantee that when generating code, because of cases like `model` where an output is generated implicitly.

These changes widen the type to be any string.
2026-03-20 15:18:29 -07:00
Kristiyan Kostadinov 22f8b0a500 fix(core): resolver function not matching expected type
Fixes that the `ɵɵresolveWindow` function wasn't match the type expected by `ɵɵlistener`. I've also added explicit type annotations to make cases like this easier to catch.
2026-03-20 15:18:29 -07:00
Matt Lewis 5a712d42d1 fix(compiler): prevent shimCssText from adding extra blank lines per CSS comment
The comment placeholder restoration in `shimCssText` appended an unconditional
`+ '\n'` to each non-hash comment replacement. Because `_commentRe` does not
consume the newline that follows a comment in the source, that newline already
remains in `cssText`. The extra `'\n'` was therefore inserted on top of the
existing one, shifting every line after each comment down by one. In files with
many comments (e.g. large SCSS preambles) this shifts all subsequent CSS rules
far enough that the CSS sourcemap — generated before `shimCssText` runs —
points to completely wrong source locations in browser DevTools.

The fix is to drop the `+ '\n'`; internal newlines within a multi-line comment
are still preserved via `_newLinesRe`, and the trailing newline that follows the
comment in `cssText` is already present without any extra injection.
2026-03-20 15:17:31 -07:00
Angular Robot 275a436a33 build: lock file maintenance
See associated pull request for more information.
2026-03-20 15:11:24 -07:00
Alex Rickabaugh df8b020299 fix(forms): clear native date inputs correctly in signal forms when changed via native UI
When a native date input gets cleared manually by a user via the internal browser
UI, the element changes from invalid to valid, but no `input` event is emitted.

This commit introduces `InputValidityMonitor`, an injectable service that
intercepts these edge-case native status changes. The monitor dynamically
installs CSP-compliant styles appending specific animation keyframes for
`:valid` and `:invalid` pseudoclasses on native form controls. By attaching an
`animationstart` listener, Angular intercepts these changes immediately and
re-invokes the parser.

Fixes #67300
2026-03-20 15:10:26 -07:00
Alex Rickabaugh 98c5afdb02 perf(forms): lazily instantiate signal form fields
Currently, Signal Forms eagerly instantiates all nodes in the form tree because `childrenMap` iterates over the `value` and creates a `FieldNode` for every property. This ensures validation side-effects are run early, but creates pure overhead for fields without validation logic unless explicitly accessed.

This commit makes `childrenMap` lazy by default, skipping materialization for children without schema logic. This is achieved by introducing `hasLogicRules()` and `anyChildHasLogic()` across the `LogicNode` hierarchy. Fields are now only instantiated when a direct read occurs via `getChild()` (which calls the new `ensureChildrenMap()`) or if their subtree requires eager evaluation due to existing validation rules.

Fixes #67212
2026-03-20 15:09:26 -07:00
Alex Rickabaugh 50e599e73e fix(core): lazy-initialize debounced state to prevent computation cycle
When building a debounced resource, we previously eagerly started tracking the 'source' signal state by instantiating a regular signal. However, if this 'debounced' primitive is initialized in a computation reactive graph (like signal forms 'validateAsync'), reading the current UI source dependency eagerly can induce a cycle if we haven't finished calculating the graph node yet.

This fix uses a 'linkedSignal' block to define the eager 'source' instead. Because linkedSignals are lazy by default, this bypasses the initial eager evaluation, allowing the containing reactive graph to finish forming first without losing our timing logic inside the ambient effect().
2026-03-19 16:18:38 -07:00
Matthieu Riegler e01573fbca docs: Add callout about the Component interface. 2026-03-19 16:14:18 -07:00
Matthieu Riegler f99e7ed20f refactor(platform-browser): remove Hammer integration
The integration was deprecated in v20 and will now be removed.

BREAKING CHANGE: Hammer.js integration has been removed. Use your own implementation.
2026-03-19 16:13:20 -07:00
SkyZeroZx dacd357016 docs: add documentation for NG8023 2026-03-19 16:12:02 -07:00
SkyZeroZx ca67828ee2 refactor(compiler-cli): introduce NG8023 compile-time diagnostic for duplicate selectors
Add NG8023 extended diagnostic to report duplicate component selectors
during compilation.

This replaces the former NG0300 runtime error, ensuring the failure
occurs at build time instead of runtime.

Closes  angular#48377

BREAKING CHANGE: Elements with multiple matching selectors will now throw at compile time.
2026-03-19 16:12:02 -07:00
Jaime Burgos eb53392b10 docs(forms): add section on managing validators dynamically in form validation guide 2026-03-19 16:07:50 -07:00
Angular Robot aa5717c2f4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-19 16:07:26 -07:00
Angular Robot f7f6f8d8fc build: update all non-major dependencies
See associated pull request for more information.
2026-03-19 16:05:08 -07:00
Matthieu Riegler 836bf2064b build: exclude formating commit
Large formatting commits are just noise.
2026-03-19 15:54:27 -07:00
Jessica Janiuk dfa149dc68 fix(core): fixes a regression with animate.leave and reordering
This fixes a regression bug that resulted in reordered elements not getting properly removed from the DOM. Reused nodes were not being cleared out in this situation.

fixes: #67728
2026-03-19 15:51:57 -07:00
Alex Rickabaugh 41b1410cb8 feat(forms): support binding number|null to <input type="text">
`<input type="number">` often does not provide the desired user experience when editing numbers in
a form. MDN even [describes](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number#using_number_inputs)
how text inputs should be used in many cases instead, via `<input type="text" inputmode="numeric">`
or similar configurations. Previously, this did not work with Signal Forms without a custom input
component/directive.

This PR builds support for binding `number|null` models directly to `<input type="text">` native
controls via `[formField]`. When a model has a number or `null` value, signal forms will preserve
that status when the user makes edits/changes. Empty string values are converted to `null`, other
values are parsed as numbers, and a parse error is raised when a non-numeric value is entered.

Note that it's up to the UI developer to configure additional UI affordances such as setting an
appropriate `inputmode`, rejecting non-numeric keypresses, etc.

Fixes #66903
Fixes #66157
2026-03-19 15:26:34 -07:00
Matthieu Riegler e850643b1b feat(compiler): Support comments in html element.
```
      <div
        // comment 0
        /* comment 1 */
        attr1="value1"
        /*
           comment 2
           spanning multiple lines
        */
        attr2="value2"
      ></div>
```
2026-03-19 15:25:17 -07:00
Alex Rickabaugh 74f76d8075 feat(forms): add reloadValidation to Signal Forms to manually trigger async validation
This commit introduces a formal mechanism to manually re-trigger
asynchronous validations in Signal Forms, addressing #66994.

It exposes a `reloadValidation` method on the `FieldState` interface
that recursively cascades down the form tree and invokes the underlying
`ResourceRef`'s `reload()` method for any metadata keys tagged with the
internal `IS_ASYNC_VALIDATION_RESOURCE` symbol.

Fixes #66994
2026-03-19 15:22:13 -07:00
SkyZeroZx c1312da183 fix(common): avoid redundant image fetch on destroy with auto sizes
prevents browsers from re-fetch image during DOM teardown
when using `sizes="auto"` with lazy loading.

Fixes angular#67055
2026-03-19 15:21:16 -07:00
aparziale a73b4b7c30 fix(migrations): inject migration not work in multi-project workspace with option path
Fix inject migration in multi-project workspace. The inject migration doesn't work when targeting one of the projects due to either not finding any files in other projects or considering them external thus it throws a SchematicsException

Fixes: #66074
2026-03-19 15:20:40 -07:00
Angular Robot c9e6263e0e build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-19 15:04:54 -07:00
Angular Robot 8cace81ce1 build: update all github actions
See associated pull request for more information.
2026-03-19 15:03:20 -07:00
Angular Robot 04ddff21d8 build: update dependency aspect_rules_ts to v3.8.7
See associated pull request for more information.
2026-03-19 15:02:23 -07:00
Matthieu Riegler cc07d46e49 docs(docs-infra): fix deprecation style for light theme 2026-03-19 15:00:27 -07:00
Doug Parker 12ea6efc9d refactor: ignore pnpm-lock.yaml in Gemini code reviews
It can't give much useful feedback so this just introduces noise into Renovate PRs.
2026-03-19 14:55:55 -07:00
Matthew Beck 61967d7ad3 release: cut the v22.0.0-next.4 release 2026-03-18 20:20:19 -06:00
Matthew Beck 557f6e7841 docs: release notes for the v21.2.5 release 2026-03-18 20:14:07 -06:00
Doug Parker 785735b7a5 release: bump Angular DevTools version to 1.14.0 2026-03-18 14:11:47 -07:00
Angular Robot f02be58aa9 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-18 14:07:06 -06:00
Kristiyan Kostadinov 468874d6e0 refactor(compiler): emit types from abstract emitter
Adds an opt-in flag to emit type information through the base abstract emitter.
2026-03-18 14:05:18 -06:00
Kristiyan Kostadinov a946e26850 refactor(compiler): move more logic into abstract emitter
Moves the logic for constructing more AST nodes into the `AbstractEmitterVisitor` so it's easier to implement.

Also cleans up the visitor a bit.
2026-03-18 14:05:18 -06:00
Kristiyan Kostadinov 71cee58e89 refactor(compiler): add opt out for printing comments
Allows for consumers of the `AbstractEmitterVisitor` to determine whether comments should be printed.
2026-03-18 14:05:18 -06:00
Kristiyan Kostadinov a3fb4a5f70 refactor(compiler): clean up unused parameter
Cleans up the `escapeDollarInStrings` parameter in various places since it isn't passed anywhere.
2026-03-18 14:05:18 -06:00
Kristiyan Kostadinov c457b9b5b4 refactor(compiler): add ts-ignore comment on factory functions
Adds a `ts-ignore` comment to thew instantiation expressions in factories, because in some compilation modes we can't guarantee that they'll compile.
2026-03-18 14:05:18 -06:00
SkyZeroZx a8bf957086 docs: update import and note formatting in guides 2026-03-18 14:04:17 -06:00
Jessica Janiuk 890c97301f Revert "refactor(core): Ensure determineLongestAnimation is run synchronously after style applies"
This reverts commit 318ade062e.
2026-03-18 11:30:35 -06:00
Yenya030 57a07d0058 refactor(service-worker): remove unnecessary cast in mock redirect check
Use the typed Response.redirected property directly in the service-worker test mock instead of casting to any.
2026-03-18 11:26:21 -06:00
Yenya030 07abfbcc6c fix(service-worker): preserve redirect policy on reconstructed asset requests
Preserve the redirect mode when rebuilding asset requests in newRequestWithMetadata(). This keeps explicit redirect:error semantics intact across service-worker redirect handling.

Update the worker test mocks to model redirect defaults correctly and add focused regression coverage for redirected lazy assets with redirect:error.
2026-03-18 11:26:21 -06:00
SkyZeroZx b72a040eca docs(docs-infra): improve semantic HTML in update guide
Improves update guide's semantic HTML
2026-03-18 09:33:17 -06:00
kbrilla 0b697f1410 test(language-service): cover document symbols microsyntax cases
Add integration tests for microsyntax let/as variable extraction
in @for, @if, and structural directive template bindings.
2026-03-17 18:41:36 -06:00
kbrilla cfd0f9950c feat(language-service): add Document Symbols support for Angular templates
Add DocumentSymbol provider for Angular templates, surfacing structural
elements like components, directives, control flow blocks, and template variables
in the VS Code Outline and breadcrumbs.

resolves #65488
2026-03-17 18:41:36 -06:00
kirjs ed150e52d1 docs: add Angular Developer Skill updates
Includes:

- Imports and setup instructions

- Validation examples (sync, async, conditional)

- FieldState vs FormField distinction

- Common pitfalls and best practices

- Full-featured example application
2026-03-17 18:39:39 -06:00
marktechson 8291b16a36 docs: adds angular-developer skill
Adds a new agent skill focused on providing fundamentals to coding agents and adhering
to modern Angular code including Signals, Signal Forms and other latest updates.
2026-03-17 18:39:39 -06:00
aparziale 730684b9ce fix(migrations): prevent trailing comma syntax errors after removing NgStyle
This fixes an issue where when removing NgStyle from the imports array of a component, an extra trailing comma would be left behind if it was the last element in that component`.
2026-03-17 18:01:25 -06:00
Alex Rickabaugh 83032e3605 fix(forms): support generic unions in signal form schemas
This commit resolves an issue where using an uninstantiated generic type
parameter in a signal form model caused TypeScript compilation failures due to
distributive conditional types (#66596). The previous attempt to fix this issue
by tuple-wrapping everything caused another bug (#65535) that prevented property
access on generic unions.

This commit balances the need to resolve nested generic property access while
handling infinitely recursive generic structures without depth errors.

What changed and why:
- Base State Wrappers: Tuple wrappers (`[TModel] extends [AbstractControl]`) are
  applied to `FieldTreeBase` to safely defer generic evaluation. This prevents
  primitive unions (like `boolean`) from incorrectly evaluating to `never`.
- Naked Map Over Children: Object subfield checks (`TModel extends Record`) are
  re-evaluated as purely naked conditionals. Eager distribution over generics
  allows users to directly access shared properties of unresolved union types.
- Array Interface Deflection: `ReadonlyArrayLike<T>` generic abstraction is
  redefined as an explicit `interface` instead of a mapped `Pick` type alias.
  This optimally intercepts TypeScript from eagerly evaluating infinitely
  recursive array structures (e.g. `RecursiveType = (number | RecursiveType)[]`).
- Overloaded Context Methods: `FieldNodeContext.stateOf` and `fieldTreeOf` are
  defined as explicitly overloaded class methods and lexically bound (`this`) in
  the constructor. These changes are required to safely align the runtime bindings
  with the tautological conditionals implemented in the `RootFieldContext`
  interface structure.

Fixes #65535
2026-03-17 17:59:36 -06:00
JoostK 1eaf92077f refactor(core): declare explicit reactive node prototypes types
These type annotations allow TS to associate the object's properties
with their corresponding declaration in the interfaces, enabling
much better code navigation. For example, "Find all implementations"
for `ReactiveNode.producerRecomputeValue` now finds the implementation
in `COMPUTED_NODE` and `LINKED_SIGNAL_NODE`.
2026-03-17 14:00:11 -06:00
JoostK 523d69a768 fix(core): run linked signal equality check without reactive consumer
This commit ports the changes in #55818 from `computed` to `linkedSignal`,
which duplicates the core logic to recompute the downstream value for an
upstream change.
2026-03-17 13:59:38 -06:00
Matthieu Riegler 69fb1614ef refactor(core): remove checkNoChanges from the public API.
It's an internal API.

BREAKING CHANGE: `ChangeDetectorRef.checkNoChanges` was removed. In tests use `fixture.detectChanges()` instead.
2026-03-17 13:57:43 -06:00
yogeshwaran-c 75560ce43d fix(compiler): parse named HTML entities containing digits
The lexer's isNamedEntityEnd function stopped scanning entity names
when encountering a digit character, causing 24 valid HTML named
entities with digits in their names (e.g. &sup1;, &frac12;, &blk34;)
to be treated as plain text instead of decoded to their corresponding
Unicode characters.

Fixes #51323
2026-03-17 13:54:41 -06:00
Alan Agius a37dd59fc4 build: remove redundant Bazel lockfile update workarounds
Renovate now natively supports updating Bazel lockfiles.

This change removes the `postUpgradeTasks` workaround in Renovate config
2026-03-17 13:53:07 -06:00
Angular Robot a63c956492 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-17 13:51:38 -06:00
Alan Agius d0086e493b docs: clarify X-Forwarded-Prefix header validation rules 2026-03-17 13:50:11 -06:00
Kristiyan Kostadinov 9769560da7 fix(compiler-cli): generic types not filled out correctly in type check block
Fixes a regression caused by the recent TCB changes where we moved the type parameter processing earlier in the pipeline and stopped properly accounting for the `TcbGenericContextBehavior`.

Fixes #67704.
2026-03-17 13:21:27 -06:00
Alex Rickabaugh c4ce3f345f feat(forms): template & reactive support for FVC
Implement support for `FormUiComponent`s in both Reactive and Template-driven
forms. This allows components that use the new signal-based form control
architecture to be used seamlessly within existing Angular form paradigms.

Key changes:
- Integrated `ɵngControlCreate` and `ɵngControlUpdate` lifecycle hooks into
  `NgModel`, `FormControlDirective`, and `FormControlName`.
- Implemented branching logic to choose between the traditional `ControlValueAccessor` (CVA) path and the new FVC path based on the host element's capabilities.
- Added comprehensive unit tests for FVC integration in both Reactive (`reactive_fvc.spec.ts`) and Template-driven (`template_fvc.spec.ts`) forms, covering:
    - Value synchronization (model -> view and view -> model).
    - Status synchronization (touched, dirty, valid, invalid, pending, required).
    - Error propagation and `parseErrors` support.
    - Fallback behavior to native DOM properties (disabled, required) when FVC inputs are missing.
    - Graceful fallback to CVA when no FVC pattern is detected.
- Refined `NgModel` to correctly handle `required` validation via its existing `RequiredValidator` directive while supporting FVC for other properties.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh b2f08574e8 refactor(forms): base implementation of custom control binding in NgControl
Update `NgControl` to support binding to custom controls via the new `ngControlCreate` and
`ngControlUpdate` lifecycle hooks. This will allow Reactive and Template-driven forms to integrate
with components that use the new `FormValueControl` (FVC) binding convention.

Key changes:
- Implement synchronization of control state between `FormControl` and custom controls.
- Add support for `parseErrors` signals from custom controls, integrating them into the Reactive
  Forms validation loop via a dynamic validator.
- Convert Reactive Forms errors into `ReactiveValidationError` objects for consumption by custom
  controls.
- Update `NgModel`, `FormControlDirective`, and `FormControlName` to provide necessary dependencies
  (`Injector`, `Renderer2`) to `NgControl`.
- Rename `setUpControl` to `setUpControlValueAccessor` to clarify its role in the traditional
  CVA path.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh d1576ee92b refactor(forms): introduce signal for required validator status
Introduces an internal signal that tracks whether `Validators.required` is in the set of validators
for an `AbstractControl`. This signal is updated whenever the validators are changed.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh 9d19d2321a refactor(forms): move native utilities up to @angular/forms
Relocate some utility code into `@angular/forms` instead of the signal-forms specific entrypoint,
to facilitate their reuse in existing template & reactive forms.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh 8587b08e88 refactor(core): JIT detection of ɵngControlCreate
Adds detection of the `ɵngControlCreate` special lifecycle hook to the JIT compiler.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh 5fe0b6d269 refactor(compiler): match control instruction on attributes
Previously we were only adding the `ɵɵcontrol` instruction on property bindings. This commit
fixes that bug by adding matching on attributes as well.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh 16783d5622 refactor(core): prepare control instruction for template & reactive interop
Add `nativeElement` and a few other affordances to the control instruction implementation.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh 723abd4d57 refactor(forms): move valueAccessor selection out of ctor
Delay the selection of a CVA until after the `ɵɵcontrol` instruction has a chance to execute.
This is necessary to delay the error that would be thrown for a missing CVA until after we have a
chance to recognize we're actually on an FVC/FCC.
2026-03-17 13:18:26 -06:00
Alex Rickabaugh 3983080236 feat(forms): support ngNoCva as an opt-out for ControlValueAccessors
If `FormsModule` or `ReactiveFormsModule` is present in the scope of a
template, plain `<input>` and other form elements will get default CVA
directives added. This commit adds an `ngNoCva` attribute as a negative
selector for those directives, so `<input ngNoCva>` elements will not have
them matched.
2026-03-17 13:18:26 -06:00
Kristiyan Kostadinov b18592a1a8 build: fix failing test in forms
Fixes a test that started failing after a couple of related changes landed at the same time.
2026-03-17 15:31:35 +01:00
Leon Senft eeba51c50b refactor(forms): make markAsTouched() touch all descendants by default
`markAsTouched()` now marks all descendants as touched. In general this
method is called when controls update the model. Most controls update
leaf nodes, in which case this change has no effect.

Marking all descendants allows triggering validation for subsections of
a form, independently from having to call `submit()` on the entire form.

`markAsTouched()` now accepts a `MarkAsTouchedOptions` parameter, which
includes a `skipDescendants` property. This can be used mark only the
receiving field as touched: `node.markAsTouched({skipDescendants: true})`.
2026-03-16 16:03:36 -06:00
kirjs a94958b59b refactor(forms): Address more feedback
Minor test and type cleanup
2026-03-16 15:24:20 -06:00
kirjs b061495134 refactor(forms): Add more tests
thoroughly tests both propagation directions
2026-03-16 15:24:20 -06:00
kirjs 0d92708b33 refactor(forms): adress feedback
Drop unnecessary casts + cleanup
2026-03-16 15:24:20 -06:00
kirjs 6703e6c803 refactor(forms): add structured extract filter
It's a helper function that takes a form, and extrasts it's value unwrapping compat values and also allowing to filter them.
2026-03-16 15:24:20 -06:00
hawkgs f3e6698455 refactor(devtools): utilize new unified getControlFlowBlocks API (#66167)
Utilize the new `ng.getControlFlowBlocks` API by refactoring the existing render tree extraction code; Slighly modify @for loop details view

PR Close #66167
2026-03-16 14:17:25 -07:00
hawkgs 264f3510a7 refactor(core): abstract control flow discovery utilities (#66167)
Create a universal mechanism for adding and managing control flow discovery utilities. Those utilities are intended to be consumed by third parties via the `ng` global interface.

PR Close #66167
2026-03-16 14:17:25 -07:00
Hryhorii Avcharov 41a392d85e feat(devtools): add support for @for control flow blocks in directive explorer (#66167)
- Handle @for data in tree strategies and view extraction
- Show @for details in the UI and property tab
- Persist @for state and update UI accordingly

PR Close #66167
2026-03-16 14:17:25 -07:00
Andrew Scott 470cf430ce test(language-service): optimize language service test environment and flatten test setup
Optimization Goals:
The primary goals of this optimization are to dramatically reduce the execution time of the language-service test suite and stabilize the mock file system infrastructure. Previously, the suite suffered from significant overhead due to recreating the `MockFileSystem`, `MockServerHost`, and TypeScript `ProjectService` for every single test block, leading to redundant parsing operations, slow test initialization, and reduced spec performance.

How the Goals Were Achieved:
1. **Mock File System Optimizations (Shared State)**:
   - Evaluated that standard test files (e.g., TS/Angular lib definitions) are immutable across tests.
   - Introduced and utilized `lockMockFileSystem()` to initialize the mock `FileSystem` with `loadStandardTestFiles()` only once per test suite run rather than repeatedly per test.
   - Refactored `LanguageServiceTestEnv.setup()` to reuse the singleton file system, completely skipping redundant module loading by eagerly flagging `fsInitialized = true`.

2. **Language Service Test Environment Enhancements (TypeScript Project Reuse)**:
   - Implemented partial configuration reloads in the `Project` class via the `update()` method, removing the need to tear down and rebuild the entire `MockServerHost` and TypeScript `ProjectService` from scratch when minimal file changes (like HTML templates or local TS edits) are made dynamically by a test.
   - Applied `projectService.reloadProjects()` and `scriptInfo.reloadFromFile()` to synchronously push mock file tree invalidations to the active TS program, skipping expensive environment initialization and saving considerable latency across tests.
   - Added `projectName` identifiers inside complex isolate tests (e.g. module alias aliasing) so custom environment injections can sandbox safely without invalidating the global default environment cache.

3. **Test Suite Unification**:
   - Flattened fragmented test groups (`grp1`, `grp3`, `grp4`) into a cohesive single directory at `packages/language-service/test/`. This simplifies execution config, improves test runner concurrency, and unifies local development targeting.
   - Cleaned out broken inline debug logging and unneeded config reloading loops.

4. **Maintaining Test Isolation**:
   - **Explicit TypeScript Configuration**: While the underlying `MockFileSystem` ("disk") is aggressively reused across tests, the TypeScript `ProjectService` and its execution environment are entirely recreated for every test run to ensure isolated ASTs and module resolution caches.
   - **Strict tsconfig.json Files Array**: When a project is initialized, it explicitly defines its boundary using the strict `files: [ ... ]` array in `tsconfig.json`. This ensures that any leftover files physically on the mock disk from an older test run are completely invisible to the TS Compiler.
   - **Namespace Sandboxing**: For tests doing custom modifications (e.g., overriding module resolution paths), they utilize localized `projectName` arguments (like `"test_alias_completions"`) to configure sandboxed working directories.
2026-03-16 14:49:34 -06:00
Angular Robot 914aa521d7 build: update dependency @angular/aria to v22
See associated pull request for more information.
2026-03-16 14:48:24 -06:00
Angular Robot d1cd6dfcd4 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-16 14:46:15 -06:00
Andrew Scott 2e34924647 feat(dev-infra): add PR review agent skill
This commit introduces an AI agent skill for reviewing pull requests
against the Angular repository. It establishes guidelines for ensuring
code cleanliness, performance, testing, API design, and payload size.

It supports performing reviews through both the GitHub CLI (remote) and
local editing, factoring in package-specific guidelines (e.g., router)
and prioritizing user approval before posting comments. By checking existing
comments first, the agent can avoid duplicate reviews.

This provides the AI agent with a reproducible workflow for providing
constructive, manual PR feedback.
2026-03-16 14:25:47 -06:00
Angular Robot 5e21431ba3 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-16 12:25:12 -06:00
hawkgs dc174d1053 refactor(devtools): introduce prop-actions-menu
Implement a context menu and add it to each property in the properties pane in order to optimize the available space by consolidating the action buttons of property items with multiple of them. Property items with a single action will retain their original behavior where the action button is directly available to click right after the displayed value.
2026-03-16 12:07:32 -06:00
Angular Robot 45641f297b build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-16 10:54:41 -06:00
Angular Robot 4bbcf9f426 build: update dependency jsdom to v29
See associated pull request for more information.
2026-03-16 10:53:07 -06:00
Kristiyan Kostadinov 2bd708fb6b fix(compiler-cli): escape template literal in TCB
Fixes a regression introduced by #67381 where we weren't escaping backticks in template literals.

Fixes #67675.
2026-03-16 10:47:25 -06:00
Max Millien dc0446552a fix(core): clean up dehydrated views during HMR component replacement
During HMR, `recreateLView()` destroys the old LView and removes its
DOM nodes, but never cleans up dehydrated view DOM nodes stored in
`LContainer[DEHYDRATED_VIEWS]`. These are SSR-rendered DOM nodes
preserved by Angular's hydration system. When the new view renders,
both the old dehydrated DOM and the new DOM coexist, causing visible
duplication (e.g. `<app-shell>` header/footer appearing twice).

Call `cleanupLView` from the hydration cleanup module after
`destroyLView` and before `removeViewFromDOM` to remove any remaining
dehydrated DOM nodes before the replacement view is rendered.

Fixes #66503
2026-03-16 10:04:06 -06:00
hawkgs 77d7378ffd test(devtools): fix and update flaky component-tree tests
Due to the design of the `ng.getComponent` spy and a race condition where sometimes a `<script>` is added to the test DOM, the `getRootElements` tests used to fail sometimes because those `<script>`s were marked as roots which caused a distortion in the roots count checks. The commit addresses that and also adds an additional test for non-application root Angular components.
2026-03-16 10:03:42 -06:00
Alan Agius 4d09046362 build: remove resolution for https-proxy-agent
This is not needed.
2026-03-16 10:01:39 -06:00
SkyZeroZx 3720b2de0f docs(docs-infra): add spacing between reference option and description
Add a spacing class to `docs-reference-option` to prevent the text from appearing too close together.
2026-03-16 10:00:46 -06:00
Akash Patel b9ff865b49 docs: update uninstallation commands for Karma packages
Added 'jasmine-core' to the list of packages to uninstall when migrating to Vitest.
2026-03-16 09:59:34 -06:00
SkyZeroZx acd6f690bd docs: fix type code block language
fix type code block language
2026-03-16 09:59:08 -06:00
guidettj 7d483f28a4 docs: use lighter lodash isEqual import in equality example 2026-03-16 09:58:40 -06:00
Kristiyan Kostadinov cd656701b0 refactor(compiler): update tests after codegen changes
Updates the compliance tests to account for the recent changes.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov cf3348a9ec refactor(compiler): rename isolated tests to codegen
Renames the test target so it's a bit clearer what it's targeting.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 4636218395 refactor(compiler-cli): avoid typescript errors from debugName transform
In some cases the `debugName` transform generates a spread into the signal function parameters. This can cause compiler errors, because the functions don't have rest parameters.

These changes work around it by adding a `@ts-ignore` above it.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 4154e7db70 refactor(compiler): add ts-ignore in pipeline
Adds `@ts-ignore` comments to same places in the pipeline where we can't produce code that passes all type checks.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 40c0f53d8b refactor(compiler): add type annotations to generated code
Adds explicit type annotations to the generated code so it's able to compile.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 419944b800 refactor(compiler-cli): check if generated code compiles in compliance tests
Updates the compliance tests to check if the generated code compiles.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 4b80227efa refactor(compiler): allow leading comments on expressions
Updates the output AST to allow leading comments to be attached to expression nodes.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 7a0d6b8df2 fix(compiler-cli): transform dropping exclamationToken from properties
Fixes that the Ivy transform was dropping the `exclamationToken` from properties.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov d99ab0e040 fix(compiler): stop generating unused field
Fixes that the compiler was generating an `attrs` field on the definition which isn't used anywhere.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov 814eaba265 refactor(core): update generated code signatures
Updates the signatures of generated code to match what the compiler actually generates.
2026-03-16 09:58:18 -06:00
Angular Robot ada150c693 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-13 16:26:41 -06:00
ibrahim-hussien-dev e127927807 docs: combine multiple documentation typo fixes 2026-03-13 13:10:55 -06:00
Angular Robot ed54855f5c build: update pnpm to v10.32.1
See associated pull request for more information.
2026-03-13 13:09:26 -06:00
Alan Agius 806c9aa1de build: update rules_angular dependency commit hash.
Update rules_angular to latest sha
2026-03-13 13:07:28 -06:00
Alan Agius e8cfa44b10 refactor: ensure modules with 'declare global' are correctly handled by Rollup
Explicitly adding an `export {}` to modules containing declare global fixes an issue where Rollup would incorrectly claim that the global variable is not defined in the emitted .d.ts files.

Needed to land the latest rules_angular.
2026-03-13 13:07:28 -06:00
SkyZeroZx 7cd474d1d6 docs(docs-infra): remove tap highlight for API reference list filter
Prevents the default translucent highlight from appearing on touch devices when interacting with the API reference list filter.
2026-03-13 13:04:03 -06:00
Jessica Janiuk 318ade062e refactor(core): Ensure determineLongestAnimation is run synchronously after style applies
This adds a setTimeout, which guarantees that we call getAnimations one frame after a reflow is finished. This means getAnimations will return data, avoiding needing the expensive fallback of getComputedStyles. It also updates the cleanup to prevent a potential memory leak if the component is destroyed before the timeout runs.
2026-03-13 13:03:11 -06:00
Jessica Janiuk df659b8d0c feat(core): re-introduce nested leave animations scoped to component boundaries
This commit re-introduces support for nested leave animations with a critical adjustment to prevent cross-component blocking. Wait for nested inner `animate.leave` transitions natively only when they exist within the same component's view or its embedded tracking structures (like `@if` and `@for`).

This resolves the issue where route navigations and parental destruction would excessively stall by traversing down into child component architectures to wait for their distinct leaf animations.

BREAKING CHANGE: Leave animations are no longer limited to the element being removed.

Fixes #67633
2026-03-13 13:01:55 -06:00
Kristiyan Kostadinov 412788fac9 fix(compiler): ensure generated code compiles
Initial pass to make sure some common cases produce code that compiles.
2026-03-13 11:13:03 -06:00
Kristiyan Kostadinov ed9750d6d7 refactor(compiler-cli): update ast factories to account for type nodes
Updates the Babel and TypeScript AST factories to account to produce type nodes.
2026-03-13 11:13:03 -06:00
Kristiyan Kostadinov 1639fc565b refactor(compiler-cli): add type nodes to translator
Updates the translator and AST factories to account for type nodes.
2026-03-13 11:13:03 -06:00
Kristiyan Kostadinov 2831ff2330 refactor(compiler-cli): add generic for type nodes to AST factories
Updates the type factories and various usage sites to add a generic for type nodes.
2026-03-13 11:13:03 -06:00
Jessica Janiuk 17d8a88ddc refactor(core): Update determineLongestAnimation to account for playback rate
This updates the determineLongestAnimation code to also calculate the playback rate in with the duration, which should also account for timing when testing with playback rates changed in devtools.
2026-03-12 17:36:50 -06:00
Jordan Webster 89c9a4de30 feat(router): Add options optional parameter for withComponentInputBinding
Add `ComponentInputBindingOptions` which is used with `withComponentInputBinding` and `bindToComponentInputs`
Can set which sources to bind as follows:
* queryParams
* params
* data

feat(router): Add `options` optional parameter for `withComponentInputBinding`

Add missing ternary operator for queryParams
2026-03-12 16:36:23 -06:00
SkyZeroZx 8edcf41760 refactor(compiler-cli): add warning for matching viewport @defer trigger options
Ensures that viewport `@defer` trigger prefetch warnings occur when the viewport options are identical, including cases with empty or no parameters.
2026-03-12 16:21:02 -06:00
Angular Robot a92949421f docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-12 16:10:11 -06:00
Angular Robot 81d0807242 build: update all non-major dependencies
See associated pull request for more information.
2026-03-12 16:08:35 -06:00
Alan Agius bb628d8b50 refactor: ensure modules with 'declare global' are correctly handled by Rollup
Explicitly adding an `export {}` to modules containing `declare global` fixes an issue where Rollup would incorrectly claim that the `global` variable is not defined in the emitted `.d.ts` files.

Needed to land the latest `rules_angular`.
2026-03-12 14:58:00 -06:00
Andrew Scott dc3131c639 feat(core): TestBed.getFixture -> TestBed.getLastFixture and update implementation
TestBed.getFixture is now TestBed.getLastFixture and returns the last fixture
created rather than throwing if there are more than 1.
2026-03-12 14:57:16 -06:00
Matthieu Riegler 4874c54c08 refactor(forms): remove deprecated WithField
This commit removes, `WithField`, `WithOptionalField`, `WithoutField`
2026-03-12 14:55:46 -06:00
Alan Agius 55b2e95fef build: disable sourcemaps in esbuild_config by setting sourcemap = False
This is now possible due to a fix in esbuild rules.
2026-03-12 14:54:43 -06:00
Matthieu Riegler a38497756a build: update mermaid to 11.13.0
partial takeover of #67637
2026-03-12 14:51:09 -06:00
Joey Perrott 41cdc92303 docs: release notes for the v19.2.20 release 2026-03-12 14:47:45 -06:00
Matthew Beck 432a3de09f docs: release notes for the v20.3.18 release 2026-03-12 13:25:53 -06:00
Matthew Beck 4cbc1a1d87 release: cut the v22.0.0-next.3 release 2026-03-12 13:12:48 -06:00
Matthew Beck 5b66252acd docs: release notes for the v21.2.4 release 2026-03-12 13:00:21 -06:00
Kristiyan Kostadinov 78dea55351 fix(compiler): disallow translations of iframe src
Fixes that the compiler was allowing translations of `src` attributes in iframes which can be a security issue.
2026-03-12 11:01:26 -06:00
Kristiyan Kostadinov de0eb4c656 fix(core): sanitize translated form attributes
Fixes that we weren't sanitizing the `form` and `formaction` attributes when they're used together with translations.
2026-03-12 11:01:26 -06:00
Jessica Janiuk 999c14eaab fix(core): reverts "feat(core): add support for nested animations"
This reverts commit ea2016a6dc.

This reverts the support for nested animations due to the global scope of how nested animations were gathered.
This caused issues where on route navigations, all child nodes with animations would be queued and run before the navigation would occur.
We'll be revisiting the nested animations with a more tightened scope of when those leave animations will occur.

fixes: #67552
2026-03-12 10:58:03 -06:00
Andrew Scott 0ab344c608 docs: release notes for the vscode extension 21.2.3 release 2026-03-11 14:55:46 -07:00
wokis 3d25953e69 docs: document coverageExclude option for excluding files from coverage 2026-03-11 14:31:06 -07:00
Angular Robot ec769851d4 build: update bazel dependencies
See associated pull request for more information.
2026-03-11 14:20:12 -07:00
Jon Snow 88235a0d12 docs(forms): clarify zoneless change detection for reactive FormArray updates
Document that reactive forms model mutations such as FormArray.push() do not schedule component change detection in zoneless applications and show the recommended ways to notify Angular.

Fixes #65536
2026-03-11 14:13:17 -07:00
Alan Agius 667219230a test: remove duplicate tests (#67518)
These tests are duplicate and have been removed.

PR Close #67518
2026-03-11 13:37:33 -07:00
Alan Agius 4febb8ad31 build: update aspect_rules_js to 3.0.2 (#67518)
This updates the major version of `aspect_rules_js`.

PR Close #67518
2026-03-11 13:37:33 -07:00
Andrew Scott cfb8aff968 release: cut the v22.0.0-next.2 release 2026-03-11 13:10:36 -07:00
Andrew Scott dea3241be6 docs: release notes for the v21.2.3 release 2026-03-11 12:06:51 -07:00
cexbrayat 3c2d95aea8 refactor(forms): normalize experimental version tags in signals api
Also replaces v21.3 with v22.0, as v21.3 should not exist.
2026-03-11 11:40:06 -07:00
JoostK b401c18674 fix(core): include signal debug names in their toString() representation
The `toString()` implementations in the primitives package intended to include
the debug name, yet the debug name was evaluated during construction before it
could ever have been assigned. This commit fixes that.

The Angular wrappers override the `toString()` representation to evaluate signals
ad-hoc instead of showing their internal state, and this commit aligns their
behavior to include the debug name in `toString` as well.
2026-03-11 11:28:35 -07:00
SkyZeroZx 0837d25a70 refactor(common): Removes unused generic type parameters from KeyValueDiffers
Remove unused generic type parameters from KeyValueDiffers methods
2026-03-11 10:49:11 -07:00
Matthieu Riegler 4842f5a3b7 refactor(core): remove old resource params
G3 has been cleaned up we can drop those.
2026-03-11 10:44:12 -07:00
Angular Robot 4c532bdfb4 build: lock file maintenance
See associated pull request for more information.
2026-03-11 10:08:58 -07:00
Thomas Willberger eafce6ed09 docs: remove duplicate aria-hidden attribute in angular aria ngTree example 2026-03-11 10:03:09 -07:00
Angular Robot 563eff0f49 build: update pnpm to v10.32.0
See associated pull request for more information.
2026-03-11 09:57:53 -07:00
Angular Robot 48d9b4b2d8 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-11 09:56:36 -07:00
SkyZeroZx 66e72efef4 refactor(compiler-cli): simplifies IncrementalCompilation.fresh
Removes the `ts.Program` argument from the `IncrementalCompilation.fresh` method.
2026-03-11 09:41:02 -07:00
Ibrahim Hussien 903d51e855 docs: combine multiple documentation improvements into one PR 2026-03-11 09:29:45 -07:00
SkyZeroZx 3ce1d9a755 docs(docs-infra): fix close button clickability and prevent layout shift
Adjust the z-index to ensure the close button remains clickable.

Also remove an unnecessary `position: relative` that was causing
layout shifts in the docs UI, which resulted in a visible and
unintended layout movement.
2026-03-11 09:28:05 -07:00
hawkgs 832d428d0e refactor(devtools): change upstream and downstream signal deps icons
Update the icons with better custom ones; Introduce an icon component and an assets folder.
2026-03-11 09:25:34 -07:00
Alan Agius 71c9c6d5e5 release: bump Angular DevTools version to 1.13.0 2026-03-11 14:23:20 +01:00
Leon Senft 57ba621c81 test(forms): read only context prevents writing to field value
Test that the read only context prevents writing to a field value:

* In validation rules
* In a provided configuration
2026-03-10 15:07:42 -07:00
Leon Senft 3e7ce0dafc fix(forms): restrict SignalFormsConfig to a readonly API
Introduce `FormFieldBinding` to represent a binding between a field and
a UI control through a `FormField` directive. This interface is used to
restrict `SignalFormsConfig` and `formFieldBindings` to a readonly API.

Fix #65779.
2026-03-10 15:07:42 -07:00
Leon Senft a1a6c5282e refactor(forms): restrict reactive logic to a readonly API
Reactive logic in forms is not intended to mutate state, but this was
poorly communicated by the permissive and highly mutable field context
provided to all logic functions. This change splits all of the
state-related API into writable and readonly interfaces.

* Top-level functions that produce a `FieldTree` (e.g. `form()`) expose
  writable signals (e.g. `value: WritableSignal<T>`) and mutating
  methods (e.g. `markAsDirty()`).

* Reactive logic expose readonly signals (e.g. `value: Signal<T>`) and
  omit mutating methods.
2026-03-10 15:07:42 -07:00
Angular Robot 02a617e89e build: update dependency @rollup/plugin-babel to v7
See associated pull request for more information.
2026-03-10 13:09:06 -07:00
Matthieu Riegler a675950e44 refactor(core): interface cleanup
Should be fine to land this time.
2026-03-10 12:44:32 -07:00
Andrew Scott dbbc38ad14 refactor(compiler-cli): Export hybrid analysis from bin
This is necessary to actually use the exported symbols. Verified by building locally
2026-03-10 11:41:50 -07:00
Angular Robot 504a72f789 build: update dependency node to v22.22.1
See associated pull request for more information.
2026-03-10 11:38:07 -07:00
Kristiyan Kostadinov 8630319f74 fix(core): sanitize translated attribute bindings with interpolations
Fixes that we weren't sanitizing attribute bindings with interpolations if they're marked for translation, for example: `<a href="{{evilLink}}" i18n-href></a>`.

Also adds a bit more test coverage for our sanitization.
2026-03-10 11:13:49 -07:00
Kristiyan Kostadinov f80ac30875 build: include localize in dev app
Includes `$localize` in the dev app so it's easier to test some code paths.
2026-03-10 11:13:49 -07:00
Kristiyan Kostadinov 1866bf5d61 refactor(compiler-cli): remove more unused code
Cleans up some more usages of TS factory APIs and some unused functions.
2026-03-10 10:57:30 -07:00
Jon Snow 196933863b docs(core): clarify provideZoneChangeDetection usage in v21+
Clarify that provideZoneChangeDetection() is used to opt applications into NgZone/ZoneJS-based change detection and to configure NgZone options such as eventCoalescing.

Fixes #67498
2026-03-10 10:21:07 -07:00
Andrew Scott ba1508886d refactor(compiler-cli): Export hybrid_analysis symbols
Export symbols from hybrid_analysis from entrypoint
2026-03-10 10:18:36 -07:00
hawkgs 55c57d4af1 refactor(devtools): make signal graph visualizer reusable
Make the signal visualizer reusable by detaching it from the signal graph manager.
2026-03-10 10:14:55 -07:00
Guseyn 9794e756f9 docs: fix first-app code getHousingLocationById housing.service.ts
1. Get location by Id work with `${this.url}/${id}`
2. Method getHousingLocationById returned empty object, api return object type, locationJson[0] ?? {} - give in result empty object.
2026-03-10 10:02:37 -07:00
Guseyn 7bc7c57636 docs: fix first-app 13 step docs code row numbers
Fix docs code row numbers.
2026-03-10 09:59:04 -07:00
Kristiyan Kostadinov f9ede9ec98 fix(core): ensure definitions compile
Includes the following changes to make sure the definitions for injectable compiler:
1. The types for the `factory` function now include the `parent` parameter.
2. `ɵɵFactoryDeclaration` is now defined as a function. We need this since the provider definition gets passed into the inejctable definition by reference.
3. `ɵɵdefineInjectable`, `ɵɵdefineNgModule` and `ɵɵdefinePipe` now return the typed definition, rather than `unknown`. This aligns with what we do for components and directives.
2026-03-10 09:58:18 -07:00
Eugene Serkin 20496988b1 docs: Update migration docs for vitest
This update fixes minor grammar mistakes
2026-03-10 09:23:49 -07:00
SkyZeroZx 6073493c5b docs: Adds @see links and update defer reference 2026-03-09 16:59:39 -07:00
Andrew Scott 6bd2e7f703 refactor(compiler-cli): Export more things needed by external TCB generation
There are more things needed by external TCB generation tools
2026-03-09 16:58:48 -07:00
Sonu Kapoor 71b8159b37 test(forms): cover transformedValue without FormField context
Adds a test verifying that `transformedValue` exposes parse errors via
the returned signal's `parseErrors()` property when no FormField
context is present.

This ensures that:
- parse errors are still observable without DI-based field propagation
- the model is not updated when `parse` omits `value`
- valid input clears parse errors and updates the model

This test protects the documented contract that DI-based error
propagation is expected for FormValueControl usage, while standalone
usage relies on explicit consumption of `parseErrors()`.
2026-03-09 16:41:48 -07:00
Jessica Janiuk 8c17721333 docs: Update animation docs for element removal order
This update the docs to be clear that descendent node animations will happen before the parent node is removed.

fixes: #67526
2026-03-09 16:40:45 -07:00
Matthieu Riegler bf93ff83d8 ci: fix exclusion of manual_api_docs
On top of #67253, dev-infra should be required for docs files
2026-03-09 16:27:43 -07:00
Angular Robot af40009d42 build: update all non-major dependencies
See associated pull request for more information.
2026-03-09 16:25:30 -07:00
Miles Malerba b918beda32 feat(core): allow debouncing signals
Adds a utility `debounced` to create a debounced version of a signal,
represented as a `Resource`. The resource's value contained the
debounced value of the signal, while its status (`resolved`, `loading`,
or `error`) indicates if the value is settled, if there is a value
currently pending debounce, or if the source signal threw an error.
2026-03-09 13:21:52 -07:00
Kristiyan Kostadinov 82b758e934 refactor(compiler-cli): replace typescript usage in type reference emits
Replaces our usage of TypeScript APIs in several places that emit references to type nodes. Also deletes some unused code.
2026-03-09 11:22:53 -07:00
Matthieu Riegler 0afe3c00ae refactor(core): remove private export of getDebugNode
This is a public api
2026-03-09 11:21:19 -07:00
Angular Robot e121e25567 build: update pnpm to v10.31.0
See associated pull request for more information.
2026-03-09 11:18:08 -07:00
Andrew Scott e97f5139ec refactor(core): update componentDeclaration to include isSignal
This is in DirectiveDeclaration and in the golden files with ComponentDeclaration
so I assume it was an accidental omission.
2026-03-09 11:17:38 -07:00
Andrew Scott f81eb26e23 docs: release notes for the v21.2.2 release 2026-03-09 11:14:37 -07:00
Matthieu Riegler 263b819a75 refactor(devtools): prevent spamming the message bus
This commit adds some state on the bus to prevent sending unecessary messages to the main window.
2026-03-09 10:45:58 -07:00
Kam 03465360bd docs: add Turkish community translation of Angular documentation
add a link to the community-driven Turkish translation of Angular
documentation to make it easier for Turkish-speaking developers to
discover localized docs.

The translation project is maintained by the community and hosted at:
https://github.com/erkamyaman/angular-tr

Providing documentation in developers' native languages helps lower
the barrier to entry and supports wider Angular adoption in the
Turkish-speaking developer community.
2026-03-09 10:29:16 -07:00
Kristiyan Kostadinov 1ad2318775 build: update to the TypeScript 6 RC
Updates the repo to the TypeScript 6 release candidate.
2026-03-09 10:25:21 -07:00
hawkgs ed3dc10fea refactor(devtools): fix browser-specific styles infra
Fix browser-specific styles infrastructure. PR #62786 cleans up part of the code, but there are still services that attempt to load these stylesheets on `main`.
2026-03-09 10:21:51 -07:00
Alan Agius 786ea441e9 build: force external sourcemaps for esbuild targets
Update the `esbuild` macro in devtools to use
`external` sourcemaps by default and remove the ability to override the `sourcemap` and `sources_content` options.
This change is necessary to ensure that the build is deterministic and 100% reproducible as otherwise Firefox will not publish the build.
2026-03-06 12:13:18 -08:00
Andrew Scott 4f5c075d92 refactor(compiler-cli): export classpropertymapping from private
ClassPropertyMapping is used by the tcb_adapter so would be needed by external
TCB generation tools
2026-03-06 12:12:45 -08:00
Angular Robot 759ee22800 build: update all github actions to v7
See associated pull request for more information.
2026-03-06 10:58:35 -08:00
kbrilla cc64def294 test(language-service): add inlay hint regression and integration coverage
test(language-service): add inlay hint regression and integration coverage
2026-03-06 10:18:28 -08:00
kbrilla 5a6d88626b feat(language-service): add angular template inlay hints support
Add Angular template inlay hints end-to-end across language-service and VS Code extension server/client wiring, including inlay-specific configuration mapping, request guards, and refresh behavior.
2026-03-06 10:18:28 -08:00
kbrilla aaf6e3e079 refactor(vscode-extension): harden workspace config lifecycle
This refactoring improves the lifecycle management and configuration handling within the VS Code extension's language client.

Key changes include:
- Introduced sessionDisposables to manage resources tied to the lifespan of an LSP client session, ensuring they are properly cleaned up when the client stops without affecting global extension resources.
- Added a configuration change listener to clear the fileToIsInAngularProjectMap cache, ensuring project state is re-evaluated when settings change.
- Enhanced registerNotificationHandlers to clear the project state cache when project loading begins or completes, providing more accurate "is in Angular project" checks.
- Modified isInAngularProject to only cache positive results, allowing for recovery if a file was initially incorrectly identified as being outside an Angular project.
2026-03-06 10:18:28 -08:00
kbrilla d6e8a3c37a refactor(vscode-extension): add workspace configuration helpers and settings grouping
Add shared workspace configuration helper utilities and move extension settings to grouped configuration sections, without inlay-hint feature options yet.
2026-03-06 10:18:28 -08:00
Kristiyan Kostadinov c19066c741 refactor(core): add tracing for component creation
Adds tracing support for component creations.
2026-03-06 09:48:23 -08:00
Kristiyan Kostadinov e433ba9a80 refactor(core): track the tracing service in the LView environment
Adds the `TracingService` to the `LView[ENVIRONMENT]` so we don't have to inject it everywhere.
2026-03-06 09:48:23 -08:00
Anushka Geeta Singh 418cb61f2f docs(router): Add example of relative navigation and multiple array values
Adds an example to docs with relative navigation and multiple values in
the commands array.
2026-03-06 09:47:41 -08:00
Angular Robot d69c468bf2 build: update all github actions
See associated pull request for more information.
2026-03-05 15:02:28 -08:00
Andrew Scott ac8418d728 refactor(compiler-cli): export TCB types and methods
exports methods and types required for TCB generation. This would allow external
tools to generate TCBs using their own analysis pipelines, separate from the
compiler-cli implementations.
2026-03-05 14:35:47 -08:00
SkyZeroZx 7b27d4ff11 refactor(core): remove redundant providedIn: 'root' from IDLE_SERVICE
Remove the `providedIn: 'root'` configuration from the `IDLE_SERVICE` token
since it is redundant and does not change the default injection behavior
2026-03-05 14:31:15 -08:00
SkyZeroZx 9705ec0386 docs: add docs for IdleService and customization for the @defer idle trigger 2026-03-05 14:31:15 -08:00
Angular Robot 44b7c92faa docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-05 14:30:55 -08:00
Alan Agius dd464e586d ci: remove redundant actions/checkout steps from dev-infra workflows
Checking out the repo is not needed for these actions.
2026-03-05 14:19:10 -08:00
Andrew Scott 8217ef9b24 refactor(compiler-cli): abstract type check block metadata to be AST-free
This commit refactors the template type checking metadata interfaces to use detached, serializable metadata rather than retaining direct references to ts.Node or ts.Declaration instances.

A new tcb_adapter translates traditional TypeScript AST-bound metadata into these decoupled structures. This abstraction lays the groundwork for supporting native preprocessors (such as Rust or ts-go) which serialize metadata over JSON rather than passing live TypeScript objects.

Key changes:
- Introduced TcbDirectiveMetadata, TcbComponentMetadata, TcbReferenceMetadata, and TcbPipeMetadata to replace TypeCheckableDirectiveMeta where appropriate.
- Substituted deep TS compilation AST references with string module names and source spans to preserve out-of-band diagnostic capabilities.
- Detached generic typeParameters and transformType properties into synthesized, standalone TS mappings.
- Updated generateTypeCheckBlock and corresponding Operations to consume the new metadata.
2026-03-05 13:31:36 -08:00
Matthieu Riegler 36936872c9 refactor(core): remove createNgModuleRef
`createNgModuleRef` was aliased to `createNgModule`

BREAKING CHANGE: `createNgModuleRef` was removed, use `createNgModule` instead
2026-03-05 12:02:27 -08:00
Angular Robot 9fe820d335 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-05 11:43:25 -08:00
Andrew Scott 0964b2ca9f release: cut the v22.0.0-next.1 release 2026-03-05 10:20:16 -08:00
Alan Agius e5f99edda5 docs: add a new section on nonces and caching considerations to the security guide. 2026-03-05 10:03:31 -08:00
SkyZeroZx 9ab80f4016 docs: update http client for withXhr 2026-03-05 10:00:05 -08:00
Leon Senft c767d678cf feat(forms): add 'blur' option to debounce rule
Expands the `debounce` rule configuration to accept `'blur'`. When this option
is provided, the rule will delay model synchronization until the field loses
focus (is touched). This introduces a debouncer that defers resolution
until the framework automatically aborts pending debounces upon touch events.
2026-03-05 09:55:14 -08:00
Kristiyan Kostadinov f01901d766 fix(migrations): avoid generating invalid code in ChangeDetectionStrategy.Eager migration
Currently the migration that add `ChangeDetectionStrategy.Eager` to components tries to add the properties as last in the object literal. This can be tricky, because TS doesn't reflect the commas in the AST so we need have to do brittle string lookups to know where to insert it.

These changes switch to inserting the property before the last pre-existing property which should be a bit more robust.
2026-03-05 09:34:03 -08:00
Joey Perrott a6941adce8 build: no longer require release mode for releases
This commit updates the github.mjs configuration to set requireReleaseModeForRelease to false, removing the requirement to use release mode for releases in the angular/angular repository.
2026-03-04 14:48:55 -08:00
Doug Parker dc4cf649b6 fix(compiler-cli): ignore generated ngDevMode signal branch for code coverage
The Angular compiler unconditionally adds a debug name transform for signals
which generates a conditional on `ngDevMode` (e.g., `ngDevMode ? { debugName: "xyz" } : []`).
During testing, `ngDevMode` is true, so the true branch executes but the
false branch is never executed. Consequently, coverage tools report the
false branch as an untested line/branch, preventing 100% test coverage.

This commit adds a synthetic `/* istanbul ignore next */` comment to the
generated false branch so that Istanbul ignores it. We only include the
istanbul comment (instead of additionally including c8) to focus on the
established standard for Angular CLI/Karma coverage while maintaining
compatibility with modern Vitest setups, since @vitest/coverage-v8 now
natively respects the fallback istanbul comment.

Fixes #64583
2026-03-04 14:42:53 -08:00
Andrew Scott 72a17afaf3 fix(compiler): prevent mutation of children array in RecursiveVisitor
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.
2026-03-04 14:41:32 -08:00
Cameron Smick d4948fb6fc feat(devtools): Add preview for childSignalProp nodes to the signals-visualizer and signal-details components.
The childSignalProp nodes were added to make it easier for users to visualize and understand when signals were being passed between components. Adding the preview for the new nodes makes the data being displayed equivalent to that of other reactive nodes in the signal graph.
2026-03-04 14:28:32 -08:00
Jessica Janiuk 62676269d2 release: cut the v22.0.0-next.0 release 2026-03-04 11:47:39 -08:00
Jessica Janiuk 00a3928967 docs: release notes for the v21.2.1 release 2026-03-04 11:35:30 -08:00
Angular Robot 4422adeabf build: update cross-repo angular dependencies to c4344a4
See associated pull request for more information.
2026-03-04 10:24:21 -08:00
Jessica Janiuk fda08b7a89 refactor(core): account for shadow roots in animations
This adds a util function to get the proper target, properly accounting for shadow roots.
2026-03-04 10:16:40 -08:00
SkyZeroZx 9208421290 docs: add customization options for browser URL in routing guide 2026-03-04 10:10:26 -08:00
Jessica Janiuk 5338b5912c Revert "refactor(http): Improves base64 encoding/decoding with feature detection (#67002)"
This reverts commit aafeb1d2bd.
2026-03-04 09:19:10 -08:00
Jessica Janiuk 7eb33713b9 Revert "fix(http): correctly cache blob responses in transfer cache (#67002)"
This reverts commit 1f057afaac.
2026-03-04 09:19:10 -08:00
Jessica Janiuk 9e64147b73 fix(core): prevent child animation elements from being orphaned
When routing between two different routes, child animations were not finishing, causing elements to be left behind in the dom. The fix ensures the proper fallback is handled to avoid automatically cancelled custom events. This ensures the animation-fallback cancelling the animation actually completes, and ensures the element is removed.

fixes: #67400
2026-03-04 08:21:37 -08:00
Angular Robot 0c4021298b build: update pnpm to v10.30.3
See associated pull request for more information.
2026-03-04 08:03:20 -08:00
Angular Robot 2ffdebb292 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-04 08:02:13 -08:00
SkyZeroZx 9fa36d1a71 docs: add documentation for dynamic validation schemas 2026-03-04 08:01:32 -08:00
Kristiyan Kostadinov 2c87f21abe fix(compiler-cli): always parenthesize object literals in TCB
This is a follow-up to #67381 which introduced a subtle bug where depending on the type checking configuration, we may put an object literal directly in the TCB body which the TS compiler ends up interpreting as a block. These changes resolve the issue by always wrapping the literal in parentheses.
2026-03-04 08:00:00 -08:00
Georgi Serev e8676b5412 docs(docs-infra): add Azerbaijani community translation
Add https://angular.az (Azerbaijani) to the community translations section.
2026-03-04 07:58:18 -08:00
SkyZeroZx c6f98c723c feat(language-service): Add support for idle timeout in defer blocks
Extends language service parsing and validation to support `@defer on idle(300)`
2026-03-04 07:57:30 -08:00
SkyZeroZx 98eb24cea0 feat(core): Support optional timeout for idle deferred triggers
Allows specifying a timeout parameter for idle-based deferred triggers, enabling more granular control over when deferred actions are executed.

Closes angular#67187
2026-03-04 07:57:30 -08:00
SkyZeroZx 17d3ea44e2 feat(core): add IdleRequestOptions support to IdleService
IdleService now accepts IdleRequestOptions,
enabling configuration of requestIdleCallback behavior in compatible environments.
2026-03-04 07:57:30 -08:00
SkyZeroZx 1f057afaac fix(http): correctly cache blob responses in transfer cache (#67002)
Previously, Blob values were passed to `Uint8Array` this resulted in silently producing an empty array (length = 0) without throwing an error, leading to empty cached data

PR Close #67002
2026-03-04 15:56:59 +00:00
SkyZeroZx aafeb1d2bd refactor(http): Improves base64 encoding/decoding with feature detection (#67002)
Use feature detection for `Uint8Array.prototype.toBase64` and
`Uint8Array.fromBase64`, falling back to the existing implementation
when native support is not available

PR Close #67002
2026-03-04 15:56:59 +00:00
Angular Robot d9e40cb456 build: update dependency jasmine to v6
See associated pull request for more information.
2026-03-03 14:47:00 -08:00
Angular Robot 000100f480 build: update dependency aspect_rules_jasmine to v2.0.4
See associated pull request for more information.
2026-03-03 14:45:41 -08:00
Angular Robot 779f02a5a9 build: update cross-repo angular dependencies to 7ed27f5
See associated pull request for more information.
2026-03-03 14:45:21 -08:00
Krueger01 0e9d58ef09 refactor(compiler-cli): update old angular.io references to angular.dev
Update comment references from the old site angular.io to the new site
angular.dev.
2026-03-03 14:22:20 -08:00
Angular Robot d305a5ec2c build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-03 14:21:32 -08:00
Andrew Scott 778b748694 refactor(router): Permit deferring commit of traversal navigations
This updates the state manager to allow intercepting and deferring commits of traversal navigations.
The issues that were encountered in the past appear to be resolved in Chrome.
The behavior of redirect is still undefined in this case, so there is an added TODO.
2026-03-03 14:09:11 -08:00
Kristiyan Kostadinov f28b8f621d refactor(compiler-cli): resolve presubmit issues
Resolves issues caught during the presubmit.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov f26308813b refactor(compiler-cli): escape quotes used in string expressions
TypeScript has functionality that automatically escapes quotes in string literals. These changes update the places where we may need to do the same ourselves.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov b37fce6066 refactor(compiler-cli): delete unused utilities
Deletes utilities that we no longer use.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov befbae0dcf refactor(compiler-cli): initial decoupling from TypeScript factory APIs
Initial pass to move usages of TS `factory` APIs to the new `TcbExpr`.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov 3828ef1917 refactor(compiler-cli): introduce new primitive for generating TCB code
Introduces the `TcbExpr` class that will be used to generate TCB code without going through TypeScript's factory APIs.
2026-03-03 11:02:49 -08:00
Angular Robot db59e27e1d build: update cross-repo angular dependencies to b1b4bd0
See associated pull request for more information.
2026-03-03 10:36:25 -08:00
Angular Robot 2a11c69d52 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-03-03 09:54:32 -08:00
Andrew Scott b8fb51c462 build(dev-infra): add release automation script for zone.js
This commit introduces a new release automation script for zone.js, located at
packages/zone.js/tools/release.mts.
2026-03-03 09:14:35 -08:00
Sai Kumar Kola 46c996a977 docs: fix side navigation bar foreground colors in both dark and light modes #67379 2026-03-03 09:13:08 -08:00
SkyZeroZx ead6bb1f52 test(http): refactors HTTP client tests to use TestBed and providers
Updates HTTP client, JSONP, and XSRF tests to utilize `TestBed` for setup.
2026-03-03 09:12:36 -08:00
Ben Hong 5955738bc4 docs: modernize testing service guide 2026-03-03 09:11:59 -08:00
Andrew Scott 54f5b32a13 test(core): Adds and uses a waitFor helper
This adds a waitFor utility inspired by tools like testing-library
and convers a zone-based test to the zoneless waitFor
2026-03-03 09:11:22 -08:00
Angular Robot f390e2d6a5 build: lock file maintenance
See associated pull request for more information.
2026-03-03 09:08:23 -08:00
Angular Robot dd7736345f build: update shiki monorepo to v4
See associated pull request for more information.

Closes #67375 as a pr takeover
2026-03-02 13:21:40 -08:00
Angular Robot c90c8a1c70 build: update cross-repo angular dependencies to 2648276
See associated pull request for more information.
2026-03-02 12:22:23 -08:00
Angular Robot fdd2c11406 docs: update cross-repo adev docs
Updated Angular adev cross repo docs files.
2026-03-02 12:19:49 -08:00
Jessica Janiuk 9758ea9ee9 refactor(core): ignore infinite animations in animate api
This ensures that when calculating longest animations, we completely ignore infinite animations. This will prevent mistakes with using the API and hopefully catch any unexpected bugs.

fixes: #67350
2026-03-02 11:40:16 -08:00
Matthieu Riegler a2d5048ff3 docs: update doc for provideZoneChangeDetection
fixes #67209
2026-03-02 11:02:30 -08:00
SkyZeroZx d793ee0bb7 docs: fixed note on event replay 2026-03-02 10:59:17 -08:00
Joey Perrott 787db90e08 ci: update the path to the labeling github actions
Update the paths to the labeling github actions after the refactor in dev-infra
2026-03-02 10:55:54 -08:00
Miles Malerba 2206efa55f feat(core): add special return statuses for resource params
Allows throwing from the resource's params function to transition the
resource to a status other than resolved.

In particular, the following values can be thrown from params:
- `ResourceParamsStatus.IDLE` causes the resource to become `idle`
  (equivalent to returning `undefined`)
- `ResourceParamsStatus.LOADING` causes the resource to become `loading`
- Any `Error` object causes the resource to become `error` and report
  the error that was thrown via `.error()`

To simplify chaining together resources, this PR also introduces a
context object passed into to the `params` functon. This context
contains a `chain` function that can be used to get the value of a
resource that the params want to depend on, while automatically
propagating the idle, loading, and erorr states of the resource forward.
2026-03-02 08:47:14 -08:00
kirjs d2e33e86b9 refactor(forms): address feedback
Refactor the normalizeFormArgs utility to include the internal FieldAdapter
2026-03-02 08:46:43 -08:00
kirjs 985d828f12 refactor(forms): hide adapter in public options
Moves adapter to internal options to prevent exposure but keep compatibility.
2026-03-02 08:46:43 -08:00
Jessica Janiuk 0b59cba85d fix(core): Prevent removal of elements during drag and drop
This addresses a reported issue where elements were being fully removed from the DOM during drag and drop operations.

fixes: #67257
2026-03-02 08:46:09 -08:00
Angular Robot ab1c13fa1e build: update cross-repo angular dependencies to 90e509f
See associated pull request for more information.
2026-03-02 08:42:36 -08:00
Angular Robot 35175b0a8a build: update pnpm to v10.30.3
See associated pull request for more information.
2026-03-02 08:38:47 -08:00
Angular Robot 73b6135bf5 build: update cross-repo angular dependencies to 9cc4778
See associated pull request for more information.
2026-02-27 09:10:48 -08:00
Angular Robot a8cba4f4fd build: update dependency bazel to v8.6.0
See associated pull request for more information.
2026-02-27 09:09:51 -08:00
Jessica Janiuk 88685cb3b6 fix(core): adds transfer cache to httpResource to fix hydration
This should prevent the microtask problem with hydration and httpResource.

fixes: #62897
2026-02-27 09:09:23 -08:00
Jessica Janiuk e1bc342856 refactor(core): Ensure idle scheduler batching accounts for change detection
This updates the deadline check in requestIdleCallback to ensure change detection properly dirties the views.
2026-02-27 09:08:59 -08:00
Matthieu Riegler 9bb4f02bef build: use different default port for dev-app
Same as ADEV, currently the CLI prompts for another port if 4200 is busy but the toolchain doesn't support prompts.

By defaulting to 4201 we avoid regular CLI apps from preventing to run the dev-app
2026-02-27 09:04:15 -08:00
Angular Robot cda3e8963a build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 14:33:24 -08:00
Matthieu Riegler 03db2aefaa fix(compiler): throw on duplicate input/outputs
inputs & outputs cannot be binded to 2 different directives/components properties

Eg
```
data = model();
dataChange = output(); // throws because model already emits on the `dataChange` output

userSomething = input({alias 'user'});
user = input(); // throws because userSomething already binds to the `user` input
````

fixes #65844

BREAKING CHANGE: The compiler will throw when there a when inputs, outputs or model are binding to the same input/outputs.
2026-02-26 13:47:37 -08:00
Matthieu Riegler 3bc095d508 feat(core): Add a schematics to migrate provideHttpClient to keep using the HttpXhrBackend implementation.
Exisiting applications will be migrated to keep using the XHR backend to prevent any breaking changes. `withXhr()` is to the `provideHttpClient` provider function.
2026-02-26 13:47:02 -08:00
Matthieu Riegler 5c432fb8bb feat(http): Use FetchBackend as default for the HttpBackend implementation
This commit replaces the `XhrHttpBackend` with the `FetchBackend` as the default implementation of the `HttpBackend`.
This introduces a breaking change a the `FetchBackend` does not support the report progress for uploads.

The previous behavior (`HttpXhrBackend`) can be restored by setting `withXhr()` in the `provideHttpClient()` provider function.

DEPRECATED: `withFetch` is now deprecated, it can be safely removed.
BREAKING CHANGE: Use the `HttpXhrBackend` with `provideHttpClient(withXhr)` if you want to keep supporting upload progress reports.
2026-02-26 13:47:02 -08:00
Angular Robot f022530df4 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 13:42:06 -08:00
Joey Perrott d1ebbbe9bc build: update to latest sha of dev-infra repo
Update to the latest sha of the dev-infra repo
2026-02-26 12:42:14 -08:00
Joey Perrott 385b9485c4 build: update to latest sha of dev-infra repo
Update to the latest sha of the dev-infra repo
2026-02-26 12:22:21 -08:00
Joey Perrott 37b4d16357 ci: set up automated issue labeling
Sets up automated issue labeling action
2026-02-26 12:22:21 -08:00
Angular Robot 6585e4fc4c build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 10:33:01 -08:00
Joey Perrott 078da3cbda ci: set up linting for upcoming agent skills
Add validation/linting on CI for agent skills files
2026-02-26 10:04:26 -08:00
Joey Perrott b4f68acaa1 build: update repository locations for bazel rules
The repositories for `rules_sass`, `rules_angular`, and `rules_browsers`
were recently transferred from devversion to the angular organization.
This commit updates the internal bazel module rules to rely on
the new repository locations.
2026-02-26 09:57:12 -08:00
Angular Robot d0afeba2cb build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-26 09:43:28 -08:00
Matthieu Riegler 95f12c87aa docs: add info around route level services
fixes #67313
2026-02-26 08:19:59 -08:00
Alan Agius 4c4a3db86a refactor: move several schematics from migrations to ng-generate directories
This are not true migrations
2026-02-26 07:54:04 -08:00
Alan Agius 1102ad74f8 refactor(migrations): remove old schematics migrations
These migrations are not needed for v22.
2026-02-26 07:54:04 -08:00
Matthieu Riegler 7d92d4454b docs: add mention of identity tracking for field iterations
related to #66711
2026-02-26 07:52:55 -08:00
Angular Robot e25b775627 build: update all non-major dependencies
See associated pull request for more information.
2026-02-26 07:52:19 -08:00
Angular Robot 4243e4addc build: update all github actions
See associated pull request for more information.
2026-02-26 07:51:30 -08:00
Angular Robot 2d64e04c76 build: update bazel dependencies
See associated pull request for more information.
2026-02-26 07:49:53 -08:00
Doug Parker 01eadde28e release: bump Angular DevTools version to 1.12.0 2026-02-25 17:44:52 -08:00
Joey Perrott a57ebc9ec1 docs: release notes for the vscode extension 21.2.1 release 2026-02-25 15:39:26 -08:00
Hien de0cc817cd docs(forms): fix casing of 'FormField' to 'formField' in templates 2026-02-25 12:46:02 -08:00
Jessica Janiuk 60f7a76616 docs: release notes for the v19.2.19 release 2026-02-25 12:44:35 -08:00
Jessica Janiuk f9a92bfe4f docs: release notes for the v20.3.17 release 2026-02-25 12:07:15 -08:00
Jessica Janiuk b7f03a9298 docs: release notes for the v21.2.0 release 2026-02-25 11:30:51 -08:00
Jessica Janiuk 0b6ac7f096 docs: release notes for the v21.1.6 release 2026-02-25 11:22:33 -08:00
Angular Robot 0af53fbb12 build: update cross-repo angular dependencies
See associated pull request for more information.

Closes #67274 as a pr takeover
2026-02-25 10:17:51 -08:00
Angular Robot b68228e89d build: lock file maintenance
See associated pull request for more information.
2026-02-25 09:13:10 -08:00
Alan Agius 6d07890d63 build: update all non-major dependencies
See associated pull request for more information.

Closes #67035 as a pr takeover
2026-02-25 08:31:32 -08:00
hawkgs f9d8da6924 fix(core): bind global context to idle callback shims in @defer's idle service
Fix a Safari regression caused by `a5981b8` where the browser is unable to properly assign the `window` context to idle callback shims in `@defer` 'on idle' configuration service.
2026-02-25 08:17:57 -08:00
Sonu Kapoor 547ed65b6f docs(forms): transformedValue parse error wiring 2026-02-25 08:13:12 -08:00
Matthieu Riegler 1416eceeea refactor(http): ensure HttpClientModule always uses the xhr backend
This is a follow-up of #67231, in preparation of making the `FetchBackend` the default
2026-02-25 08:12:14 -08:00
SkyZeroZx 97ed3d9e85 refactor(common): log a warning when a KeyValuePipe receives a signal
Add signal warning for `KeyValuePipe` and consolidates the `invalidPipeArgumentError` function into a `utils`
2026-02-25 08:11:29 -08:00
hawkgs 957466d02a docs(docs-infra): scroll home features section into view on tab change
A small UX improvement where the Features section on the home page is scrolled into view when you change the feature tab.
2026-02-25 08:03:48 -08:00
Matthieu Riegler 01a179577b refactor(upgrade): remove getAngularLib/setAngularLib
Both functions were deprecated in v5 and are replaced by `getAngularJSGlobal`/`setAngularJSGlobal`

BREAKING CHANGE: Deprecated `getAngularLib`/`setAngularLib` have been removed use `getAngularJSGlobal`/`setAngularJSGlobal` instead.
2026-02-25 07:58:24 -08:00
Alan Agius d550bf713a build: update minimum supported Node.js versions
This commit updates the minimum supported Node.js versions. Node.js v20 support is dropped, and the minimum version for Node.js v22 is bumped to v22.22.0, and for v24 it is bumped to v24.13.1.

BREAKING CHANGE: Node.js v20 is no longer supported. The minimum supported Node.js versions are now v22.22.0 and v24.13.1.
2026-02-25 07:57:18 -08:00
Angular Robot 761a08c3d8 build: update dependency @types/jsdom to v28
See associated pull request for more information.
2026-02-25 07:56:10 -08:00
Angular Robot 6bfec96d41 build: update pnpm to v10.30.2
See associated pull request for more information.
2026-02-25 07:54:24 -08:00
Jessica Janiuk a5981b83a6 feat(core): support customization of @defer's on idle behavior
This commit makes the behavior of `on idle` in `@defer` configurable via DI.
It defines an `IdleService` interface that an application can implement and
provide to Angular:

```ts
@Injectable({providedIn: 'root'})
export class CustomIdleService implements IdleService {
  requestOnIdle(callback: () => void): number {...}
  cancelOnIdle(id: number): void {...}
}
```

Then the idle service can be used by providing the IDLE_SERVICE token with the custom implementation.
2026-02-24 17:19:09 -08:00
Matthieu Riegler 0cd00b91ef ci: update pullapprove for manual_api docs
The markdown files shouldn't require dev-infra approval.
2026-02-24 15:23:30 -08:00
Anushka Geeta Singh bdbb7cc7af docs: update README to clarify app setup confirmation
Improved wording to clarify how beginners can verify their environment and IDE are correctly set up after running the app.
2026-02-24 14:22:28 -08:00
Angular Robot bb2745ddbc build: update bazel dependencies
See associated pull request for more information.
2026-02-24 14:10:01 -08:00
Matthieu Riegler db11e74b3d refactor(vscode-extension): Add support for exhaustive type check in the syntax
`@default never` will be considered a keyword on its own.
2026-02-24 11:23:47 -08:00
Matthieu Riegler 9dc3ca44ec docs: add docs for @switch Exhaustive type checking 2026-02-24 10:53:43 -08:00
Munir Issa Said 035b151a17 docs: fix roadmap introduction text 2026-02-24 10:52:34 -08:00
Jaime Burgos 3683902234 feat(router): adds browserUrl input support to router links
Enables specifying a custom browser URL for router links via a new input,
allowing navigation to use an explicit browser URL in navigation options.
2026-02-24 10:51:33 -08:00
Doug Parker 306f367899 fix(core): block creation of sensitive URI attributes from ICU messages
Translators are not allowed to write HTML which creates URI attributes. I opted to ban any values going into an attribute at all, to prevent even links to malicious content, rather than just sanitizing URIs.

I also converted this blocklist into an allowlist. Now, we only allowing setting known attributes (while sanitizing URI attributes). This significantly reduces risk of missing a vulnerable attribute and does not require an exhaustive list of all potential attributes.

BREAKING CHANGE: Angular now only applies known attributes from HTML in translated ICU content. Unknown attributes are dropped and not rendered.
2026-02-24 10:50:37 -08:00
Doug Parker 8af73eb324 docs(devtools): add debugging instructions
This adds instructions on how to load and debug the Angular DevTools extension in Chrome locally, including where all the relevant sources are.
2026-02-24 09:28:05 -08:00
Doug Parker fc55996b56 refactor(devtools): don't minify debug builds.
This disables esbuild minification when building DevTools in debug mode, introducing a new `//devtools:debug` flag and a `pnpm run devtools:build:chrome:dev` script to trigger it. This should make debugging a little easier.
2026-02-24 09:28:05 -08:00
Doug Parker 384341d900 feat(devtools): deploy source maps
This adds source maps to both the dev and production builds. Since this project is open source and downloaded ahead of time, there is not much negative cost to shipping source maps in production, as this can help any developers who encounter bugs related to Angular DevTools on the page.

There is a slight performance cost to both processing the `sourceMappingURL` comment _and_ actually processing the sourcemaps. Ideally, we would use linked sourcemaps all the time, as this avoids processing this and parses only a trivial comment unless the user actually opens a debugger. Unfortunately, Chrome seems to fail to load linked sourcemaps for scripts injected into the user's page (the backend script and content scripts), so these need inlined sourcemaps to work, which somewhat increases the performance cost. These scripts should be small enough to not be a major issue, but we can consider removing them in production based on signal from the community if necessary.
2026-02-24 09:28:05 -08:00
Matthieu Riegler f30ed6bbf6 refactor(http): expose withXhr to prepare for fetch by default
This commit sets up the necessary changes that would allow us to safely migrate G3 before switch to the `FetchBackend` by default.

For now the `HttpXhrBackend` is still the default backend for the `HttpClient`.
2026-02-24 09:26:26 -08:00
Matthieu Riegler bdb6ae9dbc refactor(router): remove deprecated provideRoutes function.
`provideRoutes` was deprecated in v15.

BREAKING CHANGE: `provideRoutes()` has been removed. Use `provideRouter()` or `ROUTES` as multi token if necessary.
2026-02-24 09:25:13 -08:00
Alan Agius c57ba8c6e6 docs: consolidate validation rules for Host and X-Forwarded-Host headers into a single point. 2026-02-24 09:24:30 -08:00
Matthieu Riegler 9e0acc5930 docs: improve responsiveness of the homepage
This fixes some layout issues when on mobile.
2026-02-24 09:23:39 -08:00
Shuaib Hasan Akib 8739a22d28 docs: inline documentation and remove unused references
Replaces referenced doc blocks with inline documentation,
cleans up unused referenced code, and fixes broken list formatting
2026-02-24 09:22:50 -08:00
Jens Kuehlers dea858979e docs: minor roadmap update (Ecosystem/vitest) 2026-02-24 09:22:09 -08:00
Shuaib Hasan Akib 15b51d0777 docs: remove inconsistent padding in update page
Removes extra padding applied to the update page so its layout
matches the rest of the documentation where no padding exists
between the title and content.
2026-02-24 09:20:51 -08:00
Jessica Janiuk dba72b672c refactor(core): Update idle scheduler to respect the Idle Deadline
This updates the idle scheduler to ensure the idle deadline is respected when scheduling tasks. Otherwise the idle callback will respond to the first idle event, which may not be the most optimal time to execute the task.
2026-02-24 09:19:01 -08:00
Angular Robot 8f5214e944 build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-24 08:59:58 -08:00
SkyZeroZx c7dc7054dc docs: Add image loader config with height parameter 2026-02-23 15:30:32 -08:00
Suguru Inatomi bedfcb5644 fix(docs-infra): use shared heading ID generation logic
This commit extracts the heading ID generation logic into a shared utility
and updates both the route generation script and the markdown pipeline to use it.

This ensures consistency between the generated routes and the rendered
documentation, and fixes an issue where custom heading IDs (`{#id}`)
were ignored during route generation.

Fixes #67200
2026-02-23 15:16:52 -08:00
Matthieu Riegler fbabd092f3 docs: Add a compiler entry to the roadmap 2026-02-23 15:11:27 -08:00
Angular Robot 7ac52d8d9b build: update cross-repo angular dependencies to v21.2.0-rc.1
See associated pull request for more information.
2026-02-23 13:38:23 -08:00
Matthieu Riegler 786ef8261f fix(compiler): throw on invalid in expressions
`{{in}}` are not interpreted as `'in'` string expressions anymore.

```
<input #in /> // OK
{{in}} // throws
```

fixes #65244

BREAKING CHANGE: `in` variables will throw in template expressions.
2026-02-23 13:35:07 -08:00
marktechson 53c1a1cee7 docs: update and reformat the roadmap 2026-02-23 13:28:39 -08:00
Matthieu Riegler 488d962bc7 fix(compiler): Don't bind inputs/outputs for data- attributes
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
2026-02-23 13:23:58 -08:00
Shuaib Hasan Akib 5ac1c025f9 refactor(core): remove outdated TODO comments
Cleans up TODO comments that are no longer planned

Fixes #67191
2026-02-23 10:19:53 -08:00
Matthieu Riegler a9ac7f87d7 docs: mention browser mode debugging 2026-02-23 10:19:23 -08:00
Miles Malerba 0af9e3e9ee ci: remove mmalerba from reviewers
remove mmalerba from reviewers
2026-02-23 10:18:56 -08:00
Angular Robot 9a3f5cbacc build: update pnpm to v10.30.1
See associated pull request for more information.
2026-02-23 09:12:23 -08:00
Miles Malerba 23fd8fa586 fix(forms): use consistent error format returned from parse
Aligns the errors returned from the `parse` function in
`transformedValue` to use the same convention as the rest of signal
forms (a property called `error` that can contain a single error or list
of errors)
2026-02-23 09:11:51 -08:00
SkyZeroZx 163dd8ee38 docs: add Route Loading Strategies section and update navigation links 2026-02-23 09:11:10 -08:00
Leon Senft 1a19d61e19 refactor(forms): clean up
* Remove unused `TValue` type parameter from `FormUiControl`
* Remove unused imports
* Remove unnecessary cast
2026-02-23 09:09:55 -08:00
Alan Agius 099b4a8bbb docs: move server-side security and host validation documentation from ssr.md to security.md. 2026-02-23 09:08:51 -08:00
Alan Agius efcf76ea61 feat(docs-infra): add hideDollar option to hide the dollar sign prefix in shell code blocks.
The dollar sign is not always required.
2026-02-23 09:08:51 -08:00
Alan Agius 75fd6c0ff2 docs: convert SSR guide's important note list to HTML <ul> for proper rendering. 2026-02-23 09:08:51 -08:00
Alan Agius 944aefe854 docs: add documentation for SSR security and host validation, including details on allowedHosts configuration
This document adds more information about `allowedHost` option
2026-02-23 09:08:51 -08:00
Jaime Burgos c89d94bd58 refactor(core): guards stringify calls with ngDevMode
The `stringify` function is only needed for debugging purposes and
should not be called in production mode.
2026-02-20 13:24:28 -08:00
SkyZeroZx 38749698d0 fix(common): fix LCP image detection with duplicate URLs
Addresses an issue where the LCP image observer incorrectly identified LCP elements when the same image URL was used multiple times on a page

Fixes #53278
2026-02-20 13:23:23 -08:00
Jessica Janiuk d7ddebca90 ci: update ng-dev config and pullapprove
This updates the pullapprove to remove the auto labeling of requires: TGP and instead moves it to the ng-dev config for pr updates.
2026-02-20 11:02:10 -08:00
cexbrayat fe25c57a5c fix(forms): preserve parse errors when parse returns value
Fixes #67170 by keeping the errors even a value is returned from the parse function.
2026-02-20 10:28:54 -08:00
Enzo Cornand b9b5c279b4 refactor(core): enhance AnimationCallbackEvent.animationComplete signature
BREAKING CHANGE: change AnimationCallbackEvent.animationComplete signature

Fixes #65613
2026-02-20 10:04:00 -08:00
Ben Hong 13e019a1bb docs: add new debugging and troubleshooting di guide 2026-02-20 10:01:11 -08:00
splincode 66b472e2bc refactor(compiler-cli): improve diagnostic with help link
Add help link to extended template diagnostic messages to provide
users with additional guidance and documentation resources. This
enhancement improves developer experience by making it easier to
understand and resolve complex template issues through direct
access to relevant Angular documentation with detailed examples
and explanations for each diagnostic type.
2026-02-20 09:40:18 -08:00
Andrew Scott 246a984a5d feat(core): add TestBed.getFixture
This adds a new method to the TestBed to retrieve the most recently created component fixture. This is useful for cases where the fixture is created in a beforeEach and needs to be accessed in a test.

If multiple fixtures have been created, this method will throw an error to prevent depending on fixture creation order.
2026-02-20 09:17:54 -08:00
Matthieu Riegler 0d652ba4da refactor(common): log a warning when a JsonPipe receives a signal
The JsonPipe does not unwrap signals and `JSON.stringify` will return `undefined` for signals.
To avoid confusion, we log a warning when a signal is passed to the pipe.
2026-02-20 09:17:01 -08:00
Matthieu Riegler b7cf37d3e1 docs: improve signal demo example 2026-02-20 09:15:31 -08:00
SkyZeroZx f90e5565e0 fix(compiler-cli): detect uninvoked functions in defer trigger expressions
Wrap `@defer` trigger expressions (`when`, `prefetch when`, `hydrate when`)
in a conditional context within the TCB to enable TypeScript's TS2774
diagnostic for detecting functions used without invocation.

Previously, signals and functions passed to `when` triggers without
parentheses would silently evaluate to truthy, causing unexpected behavior.
Now the compiler reports an error when a function is used as a condition
without being called.
2026-02-20 08:57:03 -08:00
Bas ten Feld 57edfaf435 docs(docs-infra): fix typo 'requiredSync' instead of 'requireSync' 2026-02-20 08:53:20 -08:00
Matthieu Riegler fc8140cff4 docs(docs-infra): remove toString from the API docs 2026-02-20 08:51:57 -08:00
Matthieu Riegler cb4cb77053 feat(core): Add migration to add ChangeDetectionStrategy.Eager where applicable
In v22, `OnPush` becomes the default strategy. To maintain the ChangeDetection behavior of exisiting apps, components without an explicit change detectino strategy will get `Eager` assigned.
2026-02-20 08:51:18 -08:00
Jessica Janiuk cfdbb7ce6d ci: bump target version to target 22.0.0-next.0
This updates the package json to prep for the next major.
2026-02-20 08:45:20 -08:00
Angular Robot c672f9211b build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-19 18:11:51 -08:00
kbrilla 39f62fa408 perf(language-service): use lightweight project warmup for Angular analysis
avoid per-file semantic diagnostics work when warming up a newly loaded project.
add ensureProjectAnalyzed() to the language-service API and use it from the server startup path.
implement warmup through public compiler API access with existing perf tracing, and add legacy test coverage for the new warmup flow.
2026-02-19 18:11:02 -08:00
Matthieu Riegler 550b3ba01b refactor(language-service): split tests to reduce risk of timeouts
Because we've had to many timeouts recently
2026-02-19 18:10:31 -08:00
SkyZeroZx 67b22d509a docs: update NgTemplateOutlet documentation with injector 2026-02-19 16:06:24 -08:00
SkyZeroZx f68078b3e3 docs: add section on reactive context and async operations 2026-02-19 15:59:56 -08:00
SkyZeroZx bc473cf60f docs(docs-infra): preserve content before docs-card-container in adev
The tokenizer regex pattern `[^<]*` was consuming all non-`<` content
before custom HTML tags, causing lost content.

Changed to `\s*` which only allows leading whitespace, letting marked
properly tokenize preceding content.
2026-02-19 15:48:45 -08:00
Angular Robot a1501bc90a build: update rules_browsers digest to ceb5275
See associated pull request for more information.

Closes #67138 as a pr takeover
2026-02-19 15:47:47 -08:00
Angular Robot 572945652a build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-19 13:30:45 -08:00
Matthieu Riegler d501506aa6 ci: add zone.js to minimumReleaseAgeExclude
This is a package we control the release of.
2026-02-19 12:41:19 -08:00
Walter Breakell 7d21996b1e docs: fix grammar, syntax, and broken link in elements guide 2026-02-19 12:39:00 -08:00
Joey Perrott e8cc910965 docs: update changelog to note no changes in 21.1.5 release 2026-02-19 11:23:44 -08:00
Angular Robot c9d5695d0e build: update cross-repo angular dependencies
See associated pull request for more information.
2026-02-19 11:22:19 -08:00
Matthieu Riegler a5a1829ebc docs: improve lazy loading of homepage examples
The aria tab content are only instantiated when the tab is selected which also delays the prefetching.

By having the defer block around the ng-conten we actually allow angular to prefetch the chuncks without the tab being visible
2026-02-19 09:11:31 -08:00
Doug Parker b6acda1f7e release: bump Angular DevTools version to 1.11.1 2026-02-19 09:11:15 -08:00
Matthieu Riegler 2061fd8253 fix(forms): Untrack setValue in reactive forms
Reasonably, writing to an `AbstractControl` shouldn't register signal reads.

fixes #67073
2026-02-19 09:11:06 -08:00
Leon Senft fb166772d2 fix(forms): split the touched model into an input and touch output
The `touched` property was never meant to support two-way binding; a
control should not be able to dictate that a field is no longer touched.

* The `touched` input represents the touched state of the field.
* The `touch` output allows a control implementation to indicate when
  the bound field is touched.

Note the distinction is that the `touch` output indicates _when_ the
field is touched, and not _whether_ the field is touched.
2026-02-19 09:07:03 -08:00
Georgi Serev a3731a13c9 refactor(devtools): rename directive-explorer component names and folder structure
Rename `property-tab` and `signals-view` to `property-pane` and `signal-graph-pane`, and their respective children, to property indicate their purpose and role; Move `diffing` to `directive-explorer`
2026-02-19 09:00:57 -08:00
SkyZeroZx 1771d54fb7 docs(docs-infra): fixed missing gray color palette definitions for light and dark modes
Adds the missing gray color palette definitions for both light and dark modes
2026-02-19 08:54:57 -08:00
Angular Robot 1d761338b9 build: update cross-repo angular dependencies to v21.2.0-rc.0
See associated pull request for more information.
2026-02-19 08:53:49 -08:00
Angular Robot 9de63a3e35 build: update all github actions
See associated pull request for more information.
2026-02-19 08:51:34 -08:00
Matthieu Riegler 6f922c18d9 fix(devtools): fix messaging bus
The bus wasn't initialized correctly and never recieved the backend installed messages.

fixes #67143
2026-02-19 08:45:32 -08:00
Andrew Scott ac8b5ff938 release: cut the zone.js-0.16.1 release 2026-02-19 00:26:30 +00:00
Andrew Scott 42c396242f docs: release notes for the vscode extension 21.2.0 release (#67135) 2026-02-18 15:51:09 -08:00
Andrew Scott 2eb6b0da8e build: update vscode version on main to target v22 (#67133)
build: update vscode version on main to target v22
2026-02-18 15:14:31 -08:00
Matthew Beck 2d776f6be4 docs: release notes for the v21.2.0-rc.0 release 2026-02-18 14:40:17 -08:00
Matthew Beck 7199c91d82 release: bump the next branch to v21.3.0-next.0 2026-02-18 14:40:17 -08:00
4516 changed files with 311435 additions and 208873 deletions
-1
View File
@@ -1 +0,0 @@
../.gemini/skills
+178
View File
@@ -0,0 +1,178 @@
---
name: adev-writing-guide
description: Comprehensive writing guide for Angular documentation (adev). Covers Google Technical Writing standards, Angular-specific markdown extensions, code blocks, and components. You MUST use this skill any time you plan to create, edit, or review documentation files in `adev/` or `adev/src/content`.
---
# Angular Documentation (adev) Writing Guide
This skill provides comprehensive guidelines for authoring content in `adev/src/content`. It combines Google's technical writing standards with Angular-specific markdown conventions, components, and best practices.
## I. Google Technical Writing Guidelines
### Tone and Content
- **Be conversational and friendly:** Maintain a helpful yet professional tone. Avoid being overly casual.
- **Write accessibly:** Ensure documentation is understandable to a diverse global audience, including non-native English speakers.
- **Audience-first:** Focus on what the user needs to do, not just what the system does.
- **Avoid pre-announcing:** Do not mention unreleased features or make unsupported claims.
- **Use descriptive link text:** Link text should clearly indicate the destination (e.g., avoid "click here").
### Language and Grammar
- **Use second person ("you"):** Address the reader directly.
- **Prefer active voice:** Clearly state who or what is performing the action (e.g., "The system generates a token" vs "A token is generated").
- **Standard American English:** Use standard American spelling and punctuation.
- **Conditional clauses first:** Place "if" or "when" clauses before the instruction (e.g., "If you encounter an error, check the logs").
- **Define terms:** Introduce new or unfamiliar terms/acronyms upon first use.
- **Consistent terminology:** Use the same term for the same concept throughout the document.
- **Conciseness:** Aim for one idea per sentence. Keep sentences short.
### Formatting and Organization
- **Sentence case for headings:** Capitalize only the first word and proper nouns in titles and headings.
- **Lists:**
- **Numbered lists:** Use for sequential steps or prioritized items.
- **Bulleted lists:** Use for unordered collections of items.
- **Description lists:** Use for term-definition pairs.
- **Serial commas:** Use the Oxford comma (comma before the last item in a list of three or more).
- **Code formatting:** Use code font for code-related text (filenames, variables, commands).
- **UI Elements:** formatting user interface elements in **bold**.
- **Date formatting:** Use unambiguous formats (e.g., "September 4, 2024" rather than "9/4/2024").
- **Structure:** Use logical hierarchy with clear introductions and navigation. Headings should be task-based where possible.
### Images and Code Samples
- **Images:** Use simple, clear illustrations to enhance understanding.
- **Captions:** Write captions that support the image.
- **Code Samples:**
- Ensure code is correct and builds without errors.
- Follow language-specific conventions.
- **Comments:** Focus on _why_, not _what_. Avoid commenting on obvious code.
### Reference Hierarchy
1. Project-specific style guidelines (if any exist in `CONTRIBUTING.md` or similar).
2. Google Developer Documentation Style Guide.
3. Merriam-Webster (spelling).
4. Chicago Manual of Style (non-technical).
5. Microsoft Writing Style Guide (technical).
---
## II. Angular Documentation Specifics
### Code Blocks
Use the appropriate language identifier for syntax highlighting:
- **TypeScript (Angular):** Use `angular-ts` when TypeScript code examples contain inline templates.
- **HTML (Angular):** Use `angular-html` for Angular templates.
- **TypeScript (Generic):** Use `ts` for plain TypeScript.
- **HTML (Generic):** Use `html` for plain HTML.
- **Shell/Terminal:** Use `shell` or `bash`.
- **Mermaid Diagrams:** Use `mermaid`.
#### Attributes
You can enhance code blocks with attributes in curly braces `{}` after the language identifier:
- `header="Title"`: Adds a title to the code block.
- `linenums`: Enables line numbering.
- `highlight="[1, 3-5]"`: Highlights specific lines.
- `hideCopy`: Hides the copy button.
- `prefer`: Marks code as a preferred example (green border/check).
- `avoid`: Marks code as an example to avoid (red border/cross).
**Example:**
````markdown
```angular-ts {header:"My Component", linenums, highlight="[2]"}
@Component({
selector: 'my-app',
template: '<h1>Hello</h1>',
})
export class App {}
```
````
#### `<docs-code>` Component
For more advanced code block features, use the `<docs-code>` component:
- `path`: Path to a source file (e.g., `adev/src/content/examples/...`).
- `header`: Custom header text.
- `language`: Language identifier (e.g., `angular-ts`).
- `linenums`: Boolean attribute.
- `highlight`: Array of line numbers/ranges (e.g., `[[3,7], 9]`).
- `diff`: Path to diff file.
- `visibleLines`: Range of lines to show initially (collapsible).
- `region`: Region to extract from source file.
- `preview`: Boolean. Renders a live preview (StackBlitz). _Only works with standalone examples._
- `hideCode`: Boolean. Collapses code by default.
**Multifile Example:**
```html
<docs-code-multifile path="..." preview>
<docs-code path="..." />
<docs-code path="..." />
</docs-code-multifile>
```
### Alerts / Admonitions
Use specific keywords followed by a colon for alerts. These render as styled blocks.
- `NOTE:` For ancillary information.
- `TIP:` For helpful hints or shortcuts.
- `IMPORTANT:` For crucial information.
- `CRITICAL:` For warnings about potential data loss or severe issues.
- `TODO`: For incomplete documentation.
- `QUESTION:` To pose a question to the reader.
- `SUMMARY:` For section summaries.
- `TLDR:` For concise summaries.
- `HELPFUL:` For best practices.
**Example:**
```markdown
TIP: Use `ng serve` to run your application locally.
```
### Custom Components
- **Cards (`<docs-card>`):**
- Must be inside `<docs-card-container>`.
- Attributes: `title`, `link`, `href`.
- **Callouts (`<docs-callout>`):**
- Attributes: `title`, `important`, `critical`.
- **Pills (`<docs-pill>`):**
- Must be inside `<docs-pill-row>`.
- Attributes: `title`, `href`.
- **Steps / Workflow (`<docs-step>`):**
- Must be inside `<docs-workflow>`.
- Attributes: `title`.
- **Tabs (`<docs-tab>`):**
- Must be inside `<docs-tab-group>`.
- Attributes: `label`.
- **Videos (`<docs-video>`):**
- Attributes: `src` (YouTube embed URL), `alt`.
### Images
Use standard markdown syntax with optional attributes for sizing and loading behavior.
- `#small`, `#medium`: Append to image URL for sizing.
- `{loading: 'lazy'}`: Add attribute for lazy loading.
**Example:**
```markdown
![Alt Text](path/to/image.png#medium {loading: 'lazy'})
```
### Headers
- Use markdown headers (`#`, `##`, `###`).
- Ensure a logical hierarchy (don't skip levels).
- `h2` and `h3` are most common for content structure.
+135
View File
@@ -0,0 +1,135 @@
---
name: PR Review
description: Guidelines and tools for reviewing pull requests in the Angular repository.
---
# PR Review Guidelines
When reviewing a pull request for the `angular` repository, follow these essential guidelines to ensure high-quality contributions:
1. **Context & Ecosystem**:
- Keep in mind that this is the core Angular framework. Changes here can impact millions of developers.
- Be mindful of backwards compatibility. Breaking changes require strict approval processes and deprecation periods.
2. **Key Focus Areas**:
- **Comprehensive Reviews**: You **MUST always** perform a deep, comprehensive review of the _entire_ pull request. If the user asks you to look into a specific issue, file, or area of concern, you must investigate that specific area _in addition to_ reviewing the rest of the PR's substantive changes. Do not terminate your review after addressing only the user's focal point.
- **Package-Specific & Topic Guidelines**: Check if there are specific guidelines for the package or topic being modified in the `reference/` directory (e.g., `reference/router.md` or `reference/object_create_null.md`). Always prioritize these rules for their respective areas.
- **Prototype Collision & `Object.create(null)` PRs**: When reviewing PRs that swap `{}` for `Object.create(null)`, consult `reference/object_create_null.md` for technical evaluation criteria and rules.
- **Commit Messages**: Evaluate the quality of commit messages. They should explain the _why_ behind the change, not just the _what_. Someone should be able to look at the commit history years from now and clearly understand the context and reasoning for the change.
- **Code Cleanliness**: Ensure the code is readable, maintainable, and follows Angular's project standards.
- **Performance**: Look out for code that might negatively impact runtime performance or bundle size, particularly in hot paths like change detection or rendering.
- **Testing**: Ensure all new logic has comprehensive tests, including edge cases. **Do NOT run tests locally** as part of your review process. CI handles this automatically, and running tests locally is redundant and inefficient.
- **API Design**: Ensure new public APIs are well-designed, consistent with existing APIs, and properly documented.
- **Payload Size**: Pay attention to the impact of changes on the final client payload size.
3. **Execution Workflow**:
Determine the appropriate review method. If the user explicitly asks for a `remote` or `local` review in their request, that takes precedence (e.g. "leave comments on the PR" implies `remote`). Otherwise, use the GitHub MCP or available scripts to determine if the review should be `local` or `remote`.
**Common Review Practices (Applies to both Local and Remote)**
- **Preparation & Checklist**:
- First, create a task list (e.g., in `task.md`) that you can easily reference containing **all** the review requirements from the "Key Focus Areas" section (Commit Messages, Performance, Testing, etc.), along with any specific review notes or requests from the user.
- Before doing an in-depth review, expand this list into more detailed items of what you plan to explore and verify in the PR.
- As you conduct the review, check off items in this list, adding your assessment or findings underneath each item.
- At the end of your review, refer back to the checklist to ensure every single requirement was completely verified.
- **Fetch PR Metadata Safely**: When you need to read the PR description or context, do NOT use `gh pr view <PR_NUMBER>` by itself, as its default GraphQL query may fail due to lack of `read:org` and `read:discussion` token scopes. Instead, use `read_url_content` on the PR URL or use `gh pr view <PR_NUMBER> --json title,body,state,author`.
- **Check Existing Comments First**: Before formulating feedback, use the GitHub MCP or available scripts to fetch existing comments on the PR. Review this feedback to avoid duplicate comments, and incorporate its insights into your own review process.
- **Constructive Feedback**: Provide clear, actionable, and polite feedback. Explain the _why_ behind your suggestions or edits. Do **NOT** leave inline comments purely to praise, agree with, or acknowledge a correct implementation detail, as this clutters the review. If you want to praise the PR, do so in the single general PR comment.
**A. Local Code Review (If the PR is owned by the author requesting the review)**
- **Checkout**: Check out the PR branch locally (if it doesn't already exist, fetch it). If checking out the branch fails due to a worktree claim (e.g. "fatal: '<branch>' is already used by worktree at '<path>'"), do the review in that directory.
- **Review & Edit**: Execute the review directly on the code. Instead of adding inline PR comments for suggestions, format the codebase or apply the edits directly to the files.
- **Feedback**: Summarize the review findings and the concrete changes you made in a message to the user, referencing the completed items from your checklist.
- **Do NOT Commit or Push**: Leave the changes uncommitted in the working directory so the user can easily review the pending edits locally. Let the user know the changes are ready for their review, but do not ask for approval to push.
- **Resolve Comments**: Once the user confirms the changes are good and should be committed/pushed, respond to the existing comments as 'resolved' using the GitHub MCP or available scripts.
**B. Remote Code Review (For all other PRs)**
- **Batching Comments (MCP Server - Preferred)**: If you have the GitHub MCP Server configured, you **MUST** follow this workflow to avoid spamming the author with multiple notifications:
1. Create a pending review using `mcp_github-mcp-server_pull_request_review_write` (method `create`).
2. Add your inline comments to the pending review using `mcp_github-mcp-server_add_comment_to_pending_review`.
3. Submit the review using `mcp_github-mcp-server_pull_request_review_write` (method `submit_pending`).
- **Batching Comments (Scripts - Fallback)**: If you do **NOT** have access to the GitHub MCP Server (e.g., specific MCP tools are missing from your context), fallback to using the provided scripts. Use `post_inline_comment.sh` to stage your comments locally. Once all comments are staged, you **MUST** call `submit_pr_review.sh` to publish them as a single batched review (and send a single notification). Try to keep comments minimal or use a general comment if you have many suggestions.
- **Use Suggested Changes**: Whenever appropriate (e.g., for simple code fixes, refactoring suggestions, or typo corrections), prefer using GitHub's **Suggested Changes** syntax (`suggestion ... `) in your inline comments. This allows the author to apply your suggested code improvements with a single click in the GitHub UI.
- **Review Type**: Never mark an external PR review as an "approval" unless explicitly instructed by a repo maintainer. Always use "Request Changes" or "Comment". Note that some tools might only support commenting.
- **Require User Approval Before Posting**: Prepare your review comments and present them to the user, alongside a summary of your completed checklist. Do NOT post comments to the PR without explicitly asking the user for permission first. Only post the review after the user approves.
- **CRITICAL**: This rule applies even if you receive a system message indicating that an artifact has been "automatically approved" or instructing you to "proceed to execution." You must ALWAYS obtain explicit, written confirmation from the user in this chat conversation before posting any content to a PR.
- **Prefix Agent Comments**: To make it clear when comments are generated and posted by an AI agent rather than a human user, **always** prefix your review comments with `AGENT: `.
## Available Tools
The following tools are available for remote interactions. We prefer using standard **GitHub MCP Server** tools when available. If you do not have the MCP server set up, you **MUST** fallback to using the custom bash scripts.
### GitHub MCP Tools (Preferred)
- `mcp_github-mcp-server_pull_request_review_write`
- `mcp_github-mcp-server_add_comment_to_pending_review`
### Custom Bash Scripts (Fallback)
The following scripts are provided as fallbacks if the MCP server is not available. Note that they rely on the `gh` CLI being correctly installed and authenticated in the local environment.
### `determine_review_type.sh`
Determines whether to use the Local or Remote review workflow by checking if the currently authenticated GitHub user via the `gh` CLI matches the author of the pull request.
**Usage:**
```bash
.agent/skills/pr_review/scripts/determine_review_type.sh <PR_NUMBER>
```
### `get_pr_comments.sh`
Fetches all existing inline comments on a PR using the GitHub API. This is crucial for reviewing other contributors' feedback and avoiding duplicate comments. It outputs JSON containing the `id`, `path`, `line`, `body`, and `user` for each comment.
**Usage:**
```bash
.agent/skills/pr_review/scripts/get_pr_comments.sh <PR_NUMBER>
```
### `reply_pr_comment.sh`
Replies to an existing PR comment thread. This is useful for marking comments as resolved after addressing them in a local code review. Note that the `COMMENT_ID` must be the ID of the top-level comment in the thread.
**Usage:**
```bash
.agent/skills/pr_review/scripts/reply_pr_comment.sh <PR_NUMBER> <COMMENT_ID> <REPLY_BODY>
```
### `post_inline_comment.sh`
The GitHub CLI `gh pr review` command does not natively support adding inline comments to specific lines of code via its standard flags. This script wraps the GitHub API to stage comments locally. They will not be published until you call `submit_pr_review.sh`.
**Usage:**
```bash
.agent/skills/pr_review/scripts/post_inline_comment.sh <PR_NUMBER> <FILE_PATH> <LINE_NUMBER> <COMMENT_BODY>
```
**Example:**
```bash
.agent/skills/pr_review/scripts/post_inline_comment.sh 12345 "packages/core/src/render3/instructions/element.ts" 42 "AGENT: Consider the performance implications here."
```
### `submit_pr_review.sh`
Submits all locally staged inline comments as a single batched review via the GitHub Pull Request Reviews API.
**Usage:**
```bash
.agent/skills/pr_review/scripts/submit_pr_review.sh <PR_NUMBER> <EVENT_TYPE> [BODY]
```
**Options:**
- `EVENT_TYPE`: Must be `COMMENT`, `APPROVE`, or `REQUEST_CHANGES`. Never use `APPROVE` for external PRs.
- `BODY`: (Optional) A general summary comment for the review.
**Example:**
```bash
.agent/skills/pr_review/scripts/submit_pr_review.sh 12345 COMMENT "AGENT: I have left a few inline suggestions for your consideration."
```
@@ -0,0 +1,38 @@
# Rules for `Object.create(null)` and Prototype Collision Prevention
This guide outlines the technical rules and evaluation criteria for using `Object.create(null)` versus standard object literals (`{}`) or `Map` in the Angular codebase.
---
## 1. When `Object.create(null)` is Appropriate
Using `Object.create(null)` (or `Map`) is appropriate when **all** of the following conditions are met:
1. The object is used as an **internal key-value lookup map or set**.
2. The keys are **arbitrary or untrusted dynamic strings** (e.g., URL query parameters in `$locationShim`, HTML sanitizer tag sets, or `jsaction` DOM event-type resolvers).
3. Property existence is checked via direct indexing or key checks (e.g., `map[key] !== undefined` or `key in map`), where a key matching an `Object.prototype` member (such as `'toString'`, `'constructor'`, or `'hasOwnProperty'`) causes false positive matches or incorrect behavior.
---
## 2. Handling Public API and Boundary Objects
If an object receives untrusted dynamic keys **and** is exposed to public consumers or third-party code (e.g., `SimpleChanges` in `ngOnChanges`):
- **Do NOT blindly change the object to `Object.create(null)`**: Stripping `Object.prototype` from public objects is a breaking API change. Consumer code calling `.hasOwnProperty()`, `.toString()`, `.valueOf()`, or using string interpolation (`` `${obj}` ``) will fail at runtime (`TypeError: obj.hasOwnProperty is not a function`).
- **Safe Alternatives for Public Objects:**
- **`Object.hasOwn(obj, key)`**: Use `Object.hasOwn` for internal framework property lookups instead of direct index or `in` checks. This prevents prototype collision during internal reads without breaking the object's prototype for consumers.
- **Input Key Sanitization**: Filter or delete dangerous key names (`__proto__`, `constructor`, `prototype`) when populating the object.
- **`Map` or Custom Classes**: For new public APIs requiring key-value stores with dynamic keys, prefer `Map<K, V>` or dedicated classes with explicit `.get()` and `.has()` methods.
- **Deprecation / Breaking Change Process**: If changing a public object's prototype to `null` is unavoidable, it must follow Angular's formal deprecation and major version breaking change process.
---
## 3. When `Object.create(null)` Should NOT Be Used
Do not replace `{}` with `Object.create(null)` in the following scenarios:
1. **Fixed-Shape Structs and DTOs:** Objects with hardcoded static property names (e.g., `let sortedBreakpoints: {breakpoints?: number[]} = {}`). `Object.assign({}, ...)` only copies _own_ enumerable properties, so prototype properties on sources are never copied.
2. **Numeric-Key Maps:** Objects indexed by numbers (e.g., `tasksByHandleId: {[id: number]: Task}`). Numeric keys do not collide with `Object.prototype` string members.
3. **Reference Sentinels:** Objects used purely for reference identity checks (e.g., `const EMPTY_OBJECT = {}` or `const IN_PROGRESS_RESOLUTION = {}`).
4. **Internal Compiler AST and Visitor State:** Temporary objects with internally generated keys where untrusted user input cannot poison key names.
5. **Hot Performance Paths and Size-Critical Bundles:** Standard `{}` literals use V8 fast hidden classes and monomorphic inline caching. `Object.create(null)` forces V8 dictionary mode and increases minified bundle size (e.g., in inline polyfills like `event-dispatch-contract` or SSR hydration bundles).
@@ -0,0 +1,7 @@
# Router PR Review Guidelines
When reviewing pull requests that modify the Angular Router (`packages/router`), pay special attention to the following:
- **Timing Sensitivity**: The router is extremely sensitive to timing changes. Any changes that alter the asynchronous timing of navigations, resolvers, or guards are almost always breaking changes and must be scrutinized carefully.
- **Testing Practices**: Tests should usually use the `RouterTestingHarness`. Many existing tests are older and do not use this harness. Do not blindly follow the shape of existing tests when writing or reviewing new ones; encourage the use of modern testing utilities.
- **Feature Justification**: Changes to router core code should be well-justified. Consider whether the change is proven to be a core developer ask, such as resolving a highly upvoted GitHub issue or addressing a critical bug.
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail
# determine_review_type.sh <PR_NUMBER>
# Determines if the PR should be reviewed locally or remotely based on author.
if [ -z "$1" ]; then
echo "Usage: determine_review_type.sh <PR_NUMBER>"
exit 1
fi
PR_NUMBER=$1
# Get current authenticated user
CURRENT_USER=$(gh api user -q .login 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Error: Could not determine current GitHub user. Are you logged in to gh?"
exit 1
fi
# Get PR author
PR_AUTHOR=$(gh pr view "$PR_NUMBER" --json author -q .author.login 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Error: Could not retrieve PR information for $PR_NUMBER."
exit 1
fi
if [ "$CURRENT_USER" = "$PR_AUTHOR" ]; then
echo "local"
else
echo "remote"
fi
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
# get_pr_comments.sh
# Fetches existing inline comments on a PR to avoid duplicate reviews.
# Usage: ./get_pr_comments.sh <PR_NUMBER>
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <PR_NUMBER>"
exit 1
fi
PR_NUMBER="$1"
# Ensure gh cli is installed
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
# Get the current repository (e.g., angular/angular)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
# Fetch comments
gh api \
--paginate \
-H "Accept: application/vnd.github+json" \
"/repos/${REPO}/pulls/${PR_NUMBER}/comments" \
--jq '.[] | {id: .id, path: .path, line: .line, body: .body, user: .user.login}'
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
# post_inline_comment.sh
# Adds an inline comment to a specific line in a PR via the GitHub API.
# Usage: ./post_inline_comment.sh <PR_NUMBER> <FILE_PATH> <LINE_NUMBER> <COMMENT_BODY>
if [ "$#" -lt 4 ]; then
echo "Usage: $0 <PR_NUMBER> <FILE_PATH> <LINE_NUMBER> <COMMENT_BODY>"
exit 1
fi
PR_NUMBER="$1"
FILE_PATH="$2"
LINE="$3"
BODY="$4"
# Ensure gh cli is installed
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
# Get the current repository (e.g., angular/angular)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
echo "Staging inline comment for PR #${PR_NUMBER} on ${FILE_PATH}:${LINE}..."
COMMENT_FILE="/tmp/angular_pr_${PR_NUMBER}_comments.json"
if [ ! -f "$COMMENT_FILE" ]; then
echo "[]" > "$COMMENT_FILE"
fi
# Append the new comment to the JSON array
jq --arg path "${FILE_PATH}" --argjson line "${LINE}" --arg body "${BODY}" \
'. += [{"path": $path, "line": $line, "body": $body}]' "$COMMENT_FILE" > "${COMMENT_FILE}.tmp" && mv "${COMMENT_FILE}.tmp" "$COMMENT_FILE"
echo "Comment successfully staged locally. Remember to call submit_pr_review.sh when finished to publish all comments as a single review!"
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
# reply_pr_comment.sh <PR_NUMBER> <COMMENT_ID> <REPLY_BODY>
# Replies to an existing PR comment thread. Note: COMMENT_ID must be the ID of the top-level comment in the thread you are replying to.
if [ "$#" -lt 3 ]; then
echo "Usage: reply_pr_comment.sh <PR_NUMBER> <COMMENT_ID> <REPLY_BODY>"
exit 1
fi
PR_NUMBER="$1"
COMMENT_ID="$2"
BODY="$3"
# Ensure gh cli is installed
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
# Get the current repository (e.g., angular/angular)
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
# Reply to the thread using the provided comment ID
gh api \
--silent \
--method POST \
-H "Accept: application/vnd.github+json" \
"/repos/${REPO}/pulls/${PR_NUMBER}/comments/${COMMENT_ID}/replies" \
-f body="$BODY"
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -euo pipefail
# submit_pr_review.sh
# Submits a batched PR review using comments previously staged by post_inline_comment.sh
# Usage: ./submit_pr_review.sh <PR_NUMBER> <EVENT_TYPE> [BODY]
# EVENT_TYPE must be COMMENT, APPROVE, or REQUEST_CHANGES
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <PR_NUMBER> <EVENT_TYPE> [BODY]"
echo "EVENT_TYPE must be COMMENT, APPROVE, or REQUEST_CHANGES"
exit 1
fi
PR_NUMBER="$1"
EVENT="$2"
BODY="${3:-}"
COMMENT_FILE="/tmp/angular_pr_${PR_NUMBER}_comments.json"
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI could not be found. Please install and authenticate."
exit 1
fi
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
# Check if there are staged comments
COMMENTS="[]"
if [ -f "$COMMENT_FILE" ]; then
COMMENTS=$(cat "$COMMENT_FILE")
fi
echo "Submitting review for PR #${PR_NUMBER}..."
# Create the payload
PAYLOAD_FILE="/tmp/angular_pr_${PR_NUMBER}_payload.json"
jq -n --arg event "$EVENT" --arg body "$BODY" --argjson comments "$COMMENTS" \
'{event: $event, body: $body, comments: $comments}' > "$PAYLOAD_FILE"
# Post the review using the GitHub Pull Request Reviews API
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
--input "$PAYLOAD_FILE"
echo "Review submitted successfully!"
rm -f "$COMMENT_FILE"
rm -f "$PAYLOAD_FILE"
@@ -0,0 +1,104 @@
---
name: reference-signal-forms
description: Explains the mental model and architecture of the code under `packages/forms/signals`. You MUST use this skill any time you plan to work with code in `packages/forms/signals`
---
# Signal Forms Architecture
The `packages/forms/signals` directory contains the signal-based forms API for Angular.
This system differs significantly from the existing Reactive and Template-driven forms.
## Mental Model
1. **Model-Driven**: The system is built around a `WritableSignal<T>` which serves as the **single source of truth**.
Unlike Reactive Forms where the `FormControl` holds the value, here the `Signal` holds the value.
The form is merely a _view_ or _projection_ of that signal, adding form-specific state (validity, dirty, touched).
2. **Proxy-Based Traversal**: The form API (`form(signal)`) returns a `FieldTree`. This object is a **Proxy**.
It allows accessing nested fields (e.g., `myForm.user.name`) without manually creating control groups.
Accessing a property on the proxy lazily resolves or creates the corresponding `FieldNode`.
3. **Schema-Based Logic**: Validation, disabled state, and other metadata are defined separately via **Schemas**.
Schemas are applied to the form structure using functions like `apply`, `applyEach` (for arrays), and `applyWhen`.
This separates the _structure_ of the data from the _rules_ governing it.
4. **Directives as Glue**: The `[formField]` directive binds a DOM element (native input or custom control) to a `FieldNode`.
It handles:
- Syncing the value between the DOM and the Signal.
- Reflecting state (valid, touched, etc.) to the UI.
- Handling user interaction events (blur, input).
## Key Components
### 1. `FieldNode` (`src/field/node.ts`)
The central internal class representing a single field in the form graph. It aggregates several state managers:
- `structure`: Manages parent/child relationships and signal slicing.
- `validationState`: Computes `valid`, `invalid`, `errors` signals.
- `nodeState`: Tracks `touched`, `dirty`, and derived logical state.
- `metadataState`: Stores metadata like `min`, `max`, `required`.
- `submitState`: Tracks submission status and server errors.
### 2. `FieldValidationState` (`src/field/validation.ts`)
Implements `ValidationState` and manages the complexity of validation:
- **Synchronous Errors**: Derived from schema rules.
- **Asynchronous Errors**: Handled via signals, including 'pending' states.
- **Tree Errors**: Errors that bubble up or are targeted at specific fields.
- **Submission Errors**: Server-side errors injected imperatively via `submit()`.
### 3. `FormField` Directive (`src/directive/form_field.ts`)
The bridge between the `FieldNode` and the DOM.
- Selector: `[formField]`
- It supports:
- **Native Elements**: `<input>`, `<select>`, `<textarea>`.
- **Custom Controls**: Components implementing `FormValueControl` or `FormCheckboxControl`.
- **Legacy Interop**: Components implementing `ControlValueAccessor` (via `InteropNgControl`).
### 4. `Schema` (`src/api/structure.ts` & `src/api/rules`)
Defines the behavior.
- Created via `schema(fn)`.
- Applied via `apply(path, schema)`.
- Rules include validators (`required`, `pattern`, `min`, `max`) and state modifiers (`disabled`, `hidden`).
## Data Flow
1. **Read**: `form.field().value()` reads directly from the underlying signal (projected to the specific path).
2. **Write**: Writing to the form (e.g., via UI) updates the underlying signal.
3. **Validation**: A computed effect observes the value signal and runs validators defined in the schema.
## Usage Example (Conceptual)
```typescript
// 1. Define Model
const user = signal({name: '', age: 0});
// 2. Define Schema
const userRules = schema((u) => {
required(u.name);
min(u.age, 18);
});
// 3. Create Form
const userForm = form(user, userRules); // OR apply(userForm, userRules)
// 4. Bind in Template
// <input [formField]="userForm.name">
```
## Important Files
- `packages/forms/signals/src/api/structure.ts`: Public API entry points (`form`, `apply`).
- `packages/forms/signals/src/api/control.ts`: Interfaces for custom controls (`FormUiControl`).
- `packages/forms/signals/src/field/node.ts`: The `FieldNode` implementation.
- `packages/forms/signals/src/directive/form_field.ts`: The `[formField]` directive.
## Supplemental Information
- [Compiler & Core Integration](references/integration.md): Details how `[formField]` hooks into type-checking and the runtime.
@@ -0,0 +1,46 @@
# Signal Forms Integration: Compiler & Core
This document explains how the Signal Forms system hooks into the Angular compiler and runtime to provide seamless type-checking and efficient updates.
## 1. Compiler Integration (Type Checking)
The `packages/compiler` package contains specific logic to support `[formField]`. This is primarily handled in `src/typecheck/ops/signal_forms.ts`.
### Key Mechanisms:
- **Detection**: The compiler identifies a directive as a "Field Directive" if it has the `ɵNgFieldDirective` property or comes from `@angular/forms/signals`.
- **Synthetic Binding Expansion**: When you write `<input [formField]="mySignal" />`, the type checker doesn't just check `formField`. It synthetically expands this into a set of bindings for validation:
- `[value]="mySignal()"` (or `checked` for checkboxes)
- `[disabled]="mySignal.disabled()"`
- `[required]="mySignal.required()"`
- ...and so on.
- This ensures that `mySignal` (the `FieldNode`) has all the necessary properties to drive the form control.
- **Conflict Detection**: It actively prevents "double binding". If you bind `[formField]`, you are _banned_ from also binding `[value]`, `[disabled]`, `[required]`, etc., as the signal form should be the single source of truth.
- **Element Type Validation**:
- **Native Elements**: Checks that the signal's value type matches the element type (e.g., `<input type="checkbox">` requires a `boolean` signal).
- **Custom Controls**: Detects if a custom component is a "Form Value Control" (has a `value` input/output) or "Form Checkbox Control" (has a `checked` input/output) and validates against that.
### Relevant Files:
- `packages/compiler/src/typecheck/ops/signal_forms.ts`: The core Signal Forms type-checking logic, including `TcbNativeFieldOp`.
## 2. Core Runtime Integration
The `packages/core` package provides the low-level instructions that power the `FormField` directive. This allows it to do things normal directives cannot, like efficiently syncing state without change detection overhead for every property.
### Key Mechanisms:
- **`ɵngControlCreate` Hook**: The `FormField` directive defines a special method `ɵngControlCreate`, which causes the compiler to install `ɵɵControlFeature`.
- **`ɵɵcontrol` Instructions**: A `formField` binding causes the compiler to emit:
- `ɵɵcontrolCreate`: Called during the creation phase.
- `ɵɵcontrol`: Called during the update phase.
- **`ControlDirectiveHost`**: These instructions provide the directive with a `ControlDirectiveHost`. This is a privileged interface that allows the `FormField` directive to:
- **Access the Element**: Get direct access to the native element or component instance.
- **Set Inputs**: Write directly to inputs of _other directives_ on the same node (e.g., setting the `value` input of a custom control).
- **Listen to Outputs**: Subscribe to outputs of other directives (e.g., `valueChange`).
- **Bypass Templates**: It effectively acts as a "meta-directive" that manages the bindings for you, bypassing the need for explicit template syntax for every property.
### Relevant Files:
- `packages/core/src/render3/instructions/control.ts`: Implementation of `ɵɵcontrol` instructions.
- `packages/forms/signals/src/directive/form_field.ts`: The directive that implements the hook.
+56
View File
@@ -0,0 +1,56 @@
---
description: Find and fix flaky tests in the repository
---
Investigate flaky tests in the repo and propose fixes to improve stability.
High-level process:
1. Run tests in the repo to look for flakes.
- Consider using Bazel's `--runs_per_test` flag to easily find
flakes.
- Be cognizant of not exhausting all the resources on the current
machine, run a subset of tests at a time such as
`bazel test //packages/core/...`.
2. Once you find some flakes, focus on one at a time.
3. Create a new branch named `flakes/${relevantNameFromTest}`.
4. Reproduce the flake to the best of your ability.
- Consider using `--test_env JASMINE_RANDOM_SEED=1234` to
replicate the broken test ordering.
5. Debug the test to understand the failure mode.
- Consider temporarily disabling / skipping other tests with `xit`
and `fit` to narrow down where the flake might be coming from if
multiple tests are influencing each other.
- Consider temporarily ignoring Firefox tests with
`--test_tag_filters -firefox` if the flake does not appear to be
browser specific.
- Consider using `--test_sharding_strategy disabled` to run the
test in a single shard.
- Try to understand why the test was _flaky_, not just why it
_failed_. Understanding the inconsistency is important to
finding the correct fix.
6. Attempt a fix and validate with `--runs_per_test`.
- Iterate on the fix until you have something which appears to
work.
- If you find yourself stuck and not making meaningful progress,
note down what you've learned/where you're struggling, commit
what you have, look for another flake to fix, and continue. At
the end, surface to the user what you failed to fix.
- Don't try to make significant changes to Angular's runtime
behavior, focus just on making the test pass/fail consistently.
7. Commit the change with relevant details in the commit message and
move on to the next test.
- Be sure to include your theory of why the test was flaky and
how this fix eliminates or reduces that flakiness.
8. Iterate as many times as the user requests you to (default 5
branches if not otherwise specified).
9. Once you can't find any flaky tests or have iterated as many times
as requested, stop and inform the user what you found and fixed.
Additional notes:
- Multiple fixes including the same/related files can go in the same
commit or multiple commits on the same branch.
- Distinct test fixes should go in different branches, make a new one
for each investigation.
- You may push these branches to `origin`, but do not create PRs for
them.
-10
View File
@@ -159,16 +159,6 @@ common --incompatible_allow_tags_propagation
# )
build --nosandbox_default_allow_network
##################################
# Saucelabs tests settings #
# Turn on these settings with #
# --config=saucelabs #
##################################
# For saucelabs tests we don't want to enable flaky test attempts. Karma has its own integrated
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
test:saucelabs --flaky_test_attempts=1
################
# Flag Aliases #
################
+1 -1
View File
@@ -1 +1 @@
8.5.1
8.8.0
-3
View File
@@ -1,3 +0,0 @@
Language: JavaScript
BasedOnStyle: Google
ColumnLimit: 100
+2 -1
View File
@@ -7,4 +7,5 @@ code_review:
help: false
summary: false
code_review: false
ignore_patterns: []
ignore_patterns:
- pnpm-lock.yaml
-178
View File
@@ -1,178 +0,0 @@
---
name: adev-writing-guide
description: Comprehensive writing guide for Angular documentation (adev). Covers Google Technical Writing standards, Angular-specific markdown extensions, code blocks, and components. Use when authoring or reviewing content in adev/src/content.
---
# Angular Documentation (adev) Writing Guide
This skill provides comprehensive guidelines for authoring content in `adev/src/content`. It combines Google's technical writing standards with Angular-specific markdown conventions, components, and best practices.
## I. Google Technical Writing Guidelines
### Tone and Content
- **Be conversational and friendly:** Maintain a helpful yet professional tone. Avoid being overly casual.
- **Write accessibly:** Ensure documentation is understandable to a diverse global audience, including non-native English speakers.
- **Audience-first:** Focus on what the user needs to do, not just what the system does.
- **Avoid pre-announcing:** Do not mention unreleased features or make unsupported claims.
- **Use descriptive link text:** Link text should clearly indicate the destination (e.g., avoid "click here").
### Language and Grammar
- **Use second person ("you"):** Address the reader directly.
- **Prefer active voice:** Clearly state who or what is performing the action (e.g., "The system generates a token" vs "A token is generated").
- **Standard American English:** Use standard American spelling and punctuation.
- **Conditional clauses first:** Place "if" or "when" clauses before the instruction (e.g., "If you encounter an error, check the logs").
- **Define terms:** Introduce new or unfamiliar terms/acronyms upon first use.
- **Consistent terminology:** Use the same term for the same concept throughout the document.
- **Conciseness:** Aim for one idea per sentence. Keep sentences short.
### Formatting and Organization
- **Sentence case for headings:** Capitalize only the first word and proper nouns in titles and headings.
- **Lists:**
- **Numbered lists:** Use for sequential steps or prioritized items.
- **Bulleted lists:** Use for unordered collections of items.
- **Description lists:** Use for term-definition pairs.
- **Serial commas:** Use the Oxford comma (comma before the last item in a list of three or more).
- **Code formatting:** Use code font for code-related text (filenames, variables, commands).
- **UI Elements:** formatting user interface elements in **bold**.
- **Date formatting:** Use unambiguous formats (e.g., "September 4, 2024" rather than "9/4/2024").
- **Structure:** Use logical hierarchy with clear introductions and navigation. Headings should be task-based where possible.
### Images and Code Samples
- **Images:** Use simple, clear illustrations to enhance understanding.
- **Captions:** Write captions that support the image.
- **Code Samples:**
- Ensure code is correct and builds without errors.
- Follow language-specific conventions.
- **Comments:** Focus on _why_, not _what_. Avoid commenting on obvious code.
### Reference Hierarchy
1. Project-specific style guidelines (if any exist in `CONTRIBUTING.md` or similar).
2. Google Developer Documentation Style Guide.
3. Merriam-Webster (spelling).
4. Chicago Manual of Style (non-technical).
5. Microsoft Writing Style Guide (technical).
---
## II. Angular Documentation Specifics
### Code Blocks
Use the appropriate language identifier for syntax highlighting:
- **TypeScript (Angular):** Use `angular-ts` when TypeScript code examples contain inline templates.
- **HTML (Angular):** Use `angular-html` for Angular templates.
- **TypeScript (Generic):** Use `ts` for plain TypeScript.
- **HTML (Generic):** Use `html` for plain HTML.
- **Shell/Terminal:** Use `shell` or `bash`.
- **Mermaid Diagrams:** Use `mermaid`.
#### Attributes
You can enhance code blocks with attributes in curly braces `{}` after the language identifier:
- `header="Title"`: Adds a title to the code block.
- `linenums`: Enables line numbering.
- `highlight="[1, 3-5]"`: Highlights specific lines.
- `hideCopy`: Hides the copy button.
- `prefer`: Marks code as a preferred example (green border/check).
- `avoid`: Marks code as an example to avoid (red border/cross).
**Example:**
````markdown
```angular-ts {header:"My Component", linenums, highlight="[2]"}
@Component({
selector: 'my-app',
template: '<h1>Hello</h1>',
})
export class App {}
```
````
#### `<docs-code>` Component
For more advanced code block features, use the `<docs-code>` component:
- `path`: Path to a source file (e.g., `adev/src/content/examples/...`).
- `header`: Custom header text.
- `language`: Language identifier (e.g., `angular-ts`).
- `linenums`: Boolean attribute.
- `highlight`: Array of line numbers/ranges (e.g., `[[3,7], 9]`).
- `diff`: Path to diff file.
- `visibleLines`: Range of lines to show initially (collapsible).
- `region`: Region to extract from source file.
- `preview`: Boolean. Renders a live preview (StackBlitz). _Only works with standalone examples._
- `hideCode`: Boolean. Collapses code by default.
**Multifile Example:**
```html
<docs-code-multifile path="..." preview>
<docs-code path="..." />
<docs-code path="..." />
</docs-code-multifile>
```
### Alerts / Admonitions
Use specific keywords followed by a colon for alerts. These render as styled blocks.
- `NOTE:` For ancillary information.
- `TIP:` For helpful hints or shortcuts.
- `IMPORTANT:` For crucial information.
- `CRITICAL:` For warnings about potential data loss or severe issues.
- `TODO`: For incomplete documentation.
- `QUESTION:` To pose a question to the reader.
- `SUMMARY:` For section summaries.
- `TLDR:` For concise summaries.
- `HELPFUL:` For best practices.
**Example:**
```markdown
TIP: Use `ng serve` to run your application locally.
```
### Custom Components
- **Cards (`<docs-card>`):**
- Must be inside `<docs-card-container>`.
- Attributes: `title`, `link`, `href`.
- **Callouts (`<docs-callout>`):**
- Attributes: `title`, `important`, `critical`.
- **Pills (`<docs-pill>`):**
- Must be inside `<docs-pill-row>`.
- Attributes: `title`, `href`.
- **Steps / Workflow (`<docs-step>`):**
- Must be inside `<docs-workflow>`.
- Attributes: `title`.
- **Tabs (`<docs-tab>`):**
- Must be inside `<docs-tab-group>`.
- Attributes: `label`.
- **Videos (`<docs-video>`):**
- Attributes: `src` (YouTube embed URL), `alt`.
### Images
Use standard markdown syntax with optional attributes for sizing and loading behavior.
- `#small`, `#medium`: Append to image URL for sizing.
- `{loading: 'lazy'}`: Add attribute for lazy loading.
**Example:**
```markdown
![Alt Text](path/to/image.png#medium {loading: 'lazy'})
```
### Headers
- Use markdown headers (`#`, `##`, `###`).
- Ensure a logical hierarchy (don't skip levels).
- `h2` and `h3` are most common for content structure.
@@ -1,104 +0,0 @@
---
name: reference-signal-forms
description: Explains the mental model and architecture of the code under `packages/forms/signals`. You MUST use this skill any time you plan to work with code in `packages/forms/signals`
---
# Signal Forms Architecture
The `packages/forms/signals` directory contains an experimental, signal-based forms API for Angular.
This system differs significantly from the existing Reactive and Template-driven forms.
## Mental Model
1. **Model-Driven**: The system is built around a `WritableSignal<T>` which serves as the **single source of truth**.
Unlike Reactive Forms where the `FormControl` holds the value, here the `Signal` holds the value.
The form is merely a _view_ or _projection_ of that signal, adding form-specific state (validity, dirty, touched).
2. **Proxy-Based Traversal**: The form API (`form(signal)`) returns a `FieldTree`. This object is a **Proxy**.
It allows accessing nested fields (e.g., `myForm.user.name`) without manually creating control groups.
Accessing a property on the proxy lazily resolves or creates the corresponding `FieldNode`.
3. **Schema-Based Logic**: Validation, disabled state, and other metadata are defined separately via **Schemas**.
Schemas are applied to the form structure using functions like `apply`, `applyEach` (for arrays), and `applyWhen`.
This separates the _structure_ of the data from the _rules_ governing it.
4. **Directives as Glue**: The `[formField]` directive binds a DOM element (native input or custom control) to a `FieldNode`.
It handles:
- Syncing the value between the DOM and the Signal.
- Reflecting state (valid, touched, etc.) to the UI.
- Handling user interaction events (blur, input).
## Key Components
### 1. `FieldNode` (`src/field/node.ts`)
The central internal class representing a single field in the form graph. It aggregates several state managers:
- `structure`: Manages parent/child relationships and signal slicing.
- `validationState`: Computes `valid`, `invalid`, `errors` signals.
- `nodeState`: Tracks `touched`, `dirty`, `pristine`.
- `metadataState`: Stores metadata like `min`, `max`, `required`.
- `submitState`: Tracks submission status and server errors.
### 2. `ValidationState` (`src/field/validation.ts`)
Manages the complexity of validation:
- **Synchronous Errors**: Derived from schema rules.
- **Asynchronous Errors**: Handled via signals, including 'pending' states.
- **Tree Errors**: Errors that bubble up or are targeted at specific fields.
- **Submission Errors**: Server-side errors injected imperatively via `submit()`.
### 3. `FormField` Directive (`src/directive/form_field_directive.ts`)
The bridge between the `FieldNode` and the DOM.
- Selector: `[formField]`
- It supports:
- **Native Elements**: `<input>`, `<select>`, `<textarea>`.
- **Custom Controls**: Components implementing `FormUiControl` or `FormValueControl`.
- **Legacy Interop**: Components implementing `ControlValueAccessor` (via `InteropNgControl`).
### 4. `Schema` (`src/api/structure.ts` & `src/api/rules`)
Defines the behavior.
- Created via `schema(fn)`.
- Applied via `apply(path, schema)`.
- Rules include validators (`required`, `pattern`, `min`, `max`) and state modifiers (`disabled`, `hidden`).
## Data Flow
1. **Read**: `form.field.value()` reads directly from the underlying signal (projected to the specific path).
2. **Write**: Writing to the form (e.g., via UI) updates the underlying signal.
3. **Validation**: A computed effect observes the value signal and runs validators defined in the schema.
## Usage Example (Conceptual)
```typescript
// 1. Define Model
const user = signal({name: '', age: 0});
// 2. Define Schema
const userRules = schema((u) => {
required(u.name);
min(u.age, 18);
});
// 3. Create Form
const userForm = form(user, userRules); // OR apply(userForm, userRules)
// 4. Bind in Template
// <input [formField]="userForm.name">
```
## Important Files
- `packages/forms/signals/src/api/structure.ts`: Public API entry points (`form`, `apply`).
- `packages/forms/signals/src/api/control.ts`: Interfaces for custom controls (`FormUiControl`).
- `packages/forms/signals/src/field/node.ts`: The `FieldNode` implementation.
- `packages/forms/signals/src/directive/form_field_directive.ts`: The `[formField]` directive.
## Supplemental Information
- [Compiler & Core Integration](references/integration.md): Details how `[formField]` hooks into type-checking and the runtime.
@@ -1,46 +0,0 @@
# Signal Forms Integration: Compiler & Core
This document explains how the Signal Forms system hooks into the Angular compiler and runtime to provide seamless type-checking and efficient updates.
## 1. Compiler-CLI Integration (Type Checking)
The `packages/compiler-cli` package contains specific logic to support `[formField]`. This is primarily handled in `src/ngtsc/typecheck/src/ops/signal_forms.ts`.
### Key Mechanisms:
- **Detection**: The compiler identifies a directive as a "Field Directive" if it has the `ɵNgFieldDirective` property or comes from `@angular/forms/signals`.
- **Synthetic Binding Expansion**: When you write `<input [formField]="mySignal" />`, the type checker doesn't just check `formField`. It synthetically expands this into a set of bindings for validation:
- `[value]="mySignal()"` (or `checked` for checkboxes)
- `[disabled]="mySignal.disabled()"`
- `[required]="mySignal.required()"`
- ...and so on.
- This ensures that `mySignal` (the `FieldNode`) has all the necessary properties to drive the form control.
- **Conflict Detection**: It actively prevents "double binding". If you bind `[formField]`, you are _banned_ from also binding `[value]`, `[disabled]`, `[required]`, etc., as the signal form should be the single source of truth.
- **Element Type Validation**:
- **Native Elements**: Checks that the signal's value type matches the element type (e.g., `<input type="checkbox">` requires a `boolean` signal).
- **Custom Controls**: Detects if a custom component is a "Form Value Control" (has a `value` input/output) or "Form Checkbox Control" (has a `checked` input/output) and validates against that.
### Relevant Files:
- `packages/compiler-cli/src/ngtsc/typecheck/src/ops/signal_forms.ts`: The core logic for `TcbNativeFieldOp` and `SignalFormFieldOp`.
## 2. Core Runtime Integration
The `packages/core` package provides the low-level instructions that power the `FormField` directive. This allows it to do things normal directives cannot, like efficiently syncing state without change detection overhead for every property.
### Key Mechanisms:
- **`ɵngControlCreate` Hook**: The `FormField` directive defines a special method `ɵngControlCreate`.
- **`ɵɵcontrol` Instructions**: When the compiler sees `ɵngControlCreate`, it emits:
- `ɵɵcontrolCreate`: Called during the creation phase.
- `ɵɵcontrol`: Called during the update phase.
- **`ControlDirectiveHost`**: These instructions provide the directive with a `ControlDirectiveHost`. This is a privileged interface that allows the `FormField` directive to:
- **Access the Element**: Get direct access to the native element or component instance.
- **Set Inputs**: Write directly to inputs of _other directives_ on the same node (e.g., setting the `value` input of a custom control).
- **Listen to Outputs**: Subscribe to outputs of other directives (e.g., `valueChange`).
- **Bypass Templates**: It effectively acts as a "meta-directive" that manages the bindings for you, bypassing the need for explicit template syntax for every property.
### Relevant Files:
- `packages/core/src/render3/instructions/control.ts`: Implementation of `ɵɵcontrol` instructions.
- `packages/forms/signals/src/directive/form_field_directive.ts`: The directive that implements the hook.
+2
View File
@@ -43,3 +43,5 @@ c702e8af0b2144d97b93171dc2806ed1a0346762
6d3f5752f204a5a30f3c09fbf6d4a510a4522bcb
3fa7b2b136696464e0a91b5ec25c6adf272d4d6b
ad65f44877f22caadbc8b977b5b720c3c86fcc45
# commit that changed formatting
698b0288bee60b8c5926148b79b5b93f454098db
@@ -11,7 +11,6 @@ esbuild_checked_in(
config = "esbuild.conf.js",
entry_point = ":lib/main.mts",
external = [
"undici",
"pnpapi",
],
metafile = False,
@@ -36,7 +35,5 @@ ts_project(
"//:node_modules/@actions/github",
"//:node_modules/@angular/ng-dev",
"//:node_modules/@types/node",
"//:node_modules/@types/tmp",
"//:node_modules/tmp",
],
)
@@ -1,15 +1,17 @@
import {fileSync} from 'tmp';
import {writeSync} from 'node:fs';
import {writeFileSync, mkdtempSync} from 'node:fs';
import {join} from 'node:path';
import {tmpdir} from 'node:os';
import {getInput, setSecret} from '@actions/core';
let credentialFilePath: undefined | string;
export function getCredentialFilePath(): string {
if (credentialFilePath === undefined) {
const tmpFile = fileSync({postfix: '.json'});
writeSync(tmpFile.fd, getInput('serviceKey', {required: true}));
setSecret(tmpFile.name);
credentialFilePath = tmpFile.name;
const tmpDir = mkdtempSync(join(tmpdir(), 'credential-'));
const filePath = join(tmpDir, 'credential.json');
writeFileSync(filePath, getInput('serviceKey', {required: true}));
setSecret(filePath);
credentialFilePath = filePath;
}
return credentialFilePath;
}
@@ -1,6 +1,9 @@
import {fetchLongTermSupportBranchesFromNpm, ActiveReleaseTrains} from '@angular/ng-dev';
import {ReleaseConfig} from '@angular/ng-dev';
import {AuthenticatedGitClient} from '@angular/ng-dev';
import {
fetchLongTermSupportBranchesFromNpm,
ActiveReleaseTrains,
AuthenticatedGitClient,
ReleaseConfig,
} from '@angular/ng-dev';
export interface Deployment {
branch: string;
File diff suppressed because one or more lines are too long
@@ -5,7 +5,6 @@
"types": ["node"],
"lib": ["es2021"],
"experimentalDecorators": true,
"strict": true,
"skipLibCheck": true,
"noImplicitOverride": true,
"esModuleInterop": true,
@@ -13,4 +12,4 @@
"declaration": true,
"sourceMap": true
}
}
}
@@ -1,40 +0,0 @@
name: 'Saucelabs legacy test job'
description: 'Runs tests against Saucelabs (outside of Bazel)'
runs:
using: 'composite'
steps:
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Starting Saucelabs tunnel service
shell: bash
run: ./tools/saucelabs/sauce-service.sh run &
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
# test in all supported browsers on Saucelabs anyway until this job can be removed.
- name: Preparing Bazel-generated fixtures required in legacy tests
shell: bash
run: |
# Locale files are needed for i18n tests running within Saucelabs. These are added
# directly as sources so that the TypeScript compilation of `/packages/tsconfig.json`
# can succeed. Note that the base locale and currencies files are checked-in, so
# we do not need to re-generate those through Bazel.
mkdir -p packages/common/locales/extra
cp dist/bin/packages/common/locales/*.ts packages/common/locales
cp dist/bin/packages/common/locales/extra/*.ts packages/common/locales/extra
- name: Build bundle of tests to run on Saucelabs
shell: bash
run: node tools/legacy-saucelabs/build-saucelabs-test-bundle.mjs
- name: Wait and confirm Saucelabs tunnel has connected
shell: bash
run: ./tools/saucelabs/sauce-service.sh ready-wait
- name: Running tests on Saucelabs.
shell: bash
run: KARMA_WEB_TEST_MODE=SL_REQUIRED pnpm karma start ./karma-js.conf.js --single-run
- name: Stop Saucelabs tunnel service
shell: bash
run: ./tools/saucelabs/sauce-service.sh stop
+4 -4
View File
@@ -21,17 +21,17 @@ jobs:
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Build adev
# `snapshot-build` config is used to stamp the exact version with sha in the footer.
run: pnpm bazel build //adev:build.production --config=snapshot-build
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
workflow-artifact-name: 'adev-preview'
pull-number: '${{github.event.pull_request.number}}'
+11 -5
View File
@@ -8,6 +8,7 @@
name: Deploying adev preview to Firebase
on:
# zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code}
workflow_run:
workflows: ['Build adev for preview deployment']
types: [completed]
@@ -29,18 +30,23 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
token: '${{secrets.GITHUB_TOKEN}}'
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
package-manager-cache: false
- name: Configure Firebase deploy target
working-directory: ./
run: |
# We can use `npx` as the Firebase deploy actions uses it too.
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
# Use stable version release
npx -y firebase-tools@15.15.0 target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
npx -y firebase-tools@15.15.0 target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
github-token: '${{secrets.GITHUB_TOKEN}}'
workflow-artifact-name: 'adev-preview'
@@ -2,6 +2,7 @@ name: DevInfra
on:
push:
# zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code}
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review, labeled]
@@ -14,9 +15,9 @@ jobs:
runs-on: ubuntu-latest
if: github.event.repository.fork == false
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: angular/dev-infra/github-actions/branch-manager@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/branch-manager@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+22 -5
View File
@@ -25,20 +25,34 @@ jobs:
token: '${{secrets.BENCHMARK_POST_RESULTS_GITHUB_TOKEN}}'
reactions: 'rocket'
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
- uses: alessbell/pull-request-comment-branch@ef3408c9757d05f89cb525036383033a313758a0 # v2.1.0
id: comment-branch
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Specify repository as the PR branch might be from a fork.
repository: ${{steps.comment-branch.outputs.head_owner}}/${{steps.comment-branch.outputs.head_repo}}
# Checkout the pull request and assume it being trusted given we've checked
# that the action was triggered by a team member.
ref: ${{steps.comment-branch.outputs.head_ref}}
ref: ${{steps.comment-branch.outputs.head_sha}}
# We cannot use `angular/dev-infra/github-actions/npm/checkout-and-setup-node` here
# because it does not support checking out from a fork (as it lacks a `repository` input).
# Thus, we checkout and setup Node/pnpm manually.
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
- name: Install pnpm
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- run: pnpm install --frozen-lockfile
- uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
bazelrc: ./.bazelrc.user
@@ -49,7 +63,10 @@ jobs:
COMMENT_BODY: ${{ github.event.comment.body }}
run: pnpm benchmarks prepare-for-github-action "$COMMENT_BODY"
- run: pnpm benchmarks run-compare ${{steps.info.outputs.compareSha}} ${{steps.info.outputs.benchmarkTarget}}
- env:
COMPARE_SHA: ${{steps.info.outputs.compareSha}}
BENCHMARK_TARGET: ${{steps.info.outputs.benchmarkTarget}}
run: pnpm benchmarks run-compare "$COMPARE_SHA" "$BENCHMARK_TARGET"
id: benchmark
name: Running benchmark
+29 -37
View File
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Check code lint
@@ -32,6 +32,8 @@ jobs:
run: pnpm ng-dev pullapprove verify
- name: Validate angular robot configuration
run: pnpm ng-dev ngbot verify
- name: Validate agent skills
run: pnpm ng-dev misc validate-skills
- name: Confirm code builds with typescript as expected
run: pnpm check-tooling-setup
@@ -39,13 +41,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
disable-package-manager-cache: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -55,7 +57,7 @@ jobs:
- name: Test build
run: pnpm devtools:build:chrome
- name: Cypress run
uses: cypress-io/github-action@84d178e4bbce871e23f2ffa3085898cde0e4f0ec # v7.1.2
uses: cypress-io/github-action@09090944bd8aaa2a517cefb6e38bf1aae336b42b # v7.4.3
with:
command: pnpm devtools:test:e2e
start: pnpm bazel run //devtools/src:devserver
@@ -67,11 +69,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -83,11 +85,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -100,11 +102,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -119,11 +121,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -136,11 +138,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
@@ -152,11 +154,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }}
- name: Install node modules
@@ -186,31 +188,21 @@ jobs:
- run: pnpm -C packages/zone.js jest:test
- run: pnpm -C packages/zone.js jest:nodetest
- run: pnpm -C packages/zone.js vitest:test
- run: pnpm -C packages/zone.js vitest-globals:test
- run: pnpm -C packages/zone.js electrontest
- run: pnpm -C packages/zone.js/test/typings test
# saucelabs:
# runs-on: ubuntu-latest
# env:
# SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
# steps:
# - name: Initialize environment
# uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b5a3609f89c06eb4037dce22a93641213a5d1508
# - name: Install node modules
# run: pnpm install --frozen-lockfile
# - uses: ./.github/actions/saucelabs-legacy
adev-deploy:
needs: [adev]
if: needs.adev.result == 'success'
runs-on: ubuntu-latest-8core
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Build adev
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Setting `persist-credentials: false` prevents the github-action account from being the
# account that is attempted to be used for authentication, instead the remote is set to
@@ -37,7 +37,7 @@ jobs:
ANGULAR_READONLY_GITHUB_TOKEN: ${{ secrets.READONLY_GITHUB_TOKEN }}
- name: Create a PR (if necessary)
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.ANGULAR_ROBOT_ACCESS_TOKEN }}
push-to-fork: 'angular-robot/angular'
+17 -5
View File
@@ -1,25 +1,37 @@
name: DevInfra
on:
# zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code}
pull_request_target:
types: [opened, synchronize, reopened]
issues:
types: [opened, reopened]
# Declare default permissions as read only.
permissions:
contents: read
jobs:
labels:
pull_request_labels:
if: github.event_name == 'pull_request_target'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: angular/dev-infra/github-actions/pull-request-labeling@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/labeling/pull-request@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
labels: '{"requires: TGP": ["packages/core/primitives/**/{*,.*}"]}'
post_approval_changes:
if: github.event_name == 'pull_request_target'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: angular/dev-infra/github-actions/post-approval-changes@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/post-approval-changes@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
issue_labels:
if: github.event_name == 'issues'
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/labeling/issue@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
google-generative-ai-key: ${{ secrets.GOOGLE_GENERATIVE_AI_KEY }}
+3 -2
View File
@@ -1,6 +1,7 @@
name: Google Internal Tests Enforcement
on:
# zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code}
pull_request_target:
types: [opened, reopened, synchronize]
@@ -13,8 +14,8 @@ jobs:
statuses: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: angular/dev-infra/github-actions/google-internal-tests@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: angular/dev-infra/github-actions/google-internal-tests@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
run-tests-guide-url: http://go/angular-g3sync-start
github-token: ${{ secrets.GITHUB_TOKEN }}
-32
View File
@@ -1,32 +0,0 @@
name: Manual jobs
on:
workflow_dispatch:
inputs: {}
jobs:
# Bazel saucelabs job resides in `manual.yml` because it's currently unstable, but
# kept as "runnable" for debugging/stabilization effort purposes.
bazel-saucelabs:
runs-on: ubuntu-latest
env:
JOBS: 2
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Setup Saucelabs Variables
uses: angular/dev-infra/github-actions/saucelabs@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- name: Set up Sauce Tunnel Daemon
run: pnpm bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
env:
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
- name: Run all saucelabs bazel tests
run: |
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "fixme-saucelabs", ...)')
pnpm bazel test --config=saucelabs --jobs=$JOBS ${TESTS}
+4 -2
View File
@@ -1,6 +1,8 @@
name: Merge Ready
on: pull_request_target
on:
# zizmor: ignore[dangerous-triggers] - {Trigger is safe as workflow does not checkout untrusted code}
pull_request_target:
# Declare default permissions as read only.
permissions: {}
@@ -9,6 +11,6 @@ jobs:
status:
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/unified-status-check@7c08ac2a4f396bad752829fba09dbaefbcded9fc
- uses: angular/dev-infra/github-actions/unified-status-check@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+10 -5
View File
@@ -7,7 +7,6 @@ on:
permissions:
contents: 'read'
id-token: 'write'
defaults:
run:
@@ -21,7 +20,7 @@ jobs:
workflows: ${{ steps.workflows.outputs.workflows }}
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- id: workflows
@@ -31,14 +30,17 @@ jobs:
timeout-minutes: 30
runs-on: ubuntu-latest
needs: list
permissions:
contents: 'read'
id-token: 'write'
strategy:
matrix:
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
# We utilize the google-github-actions/auth action to allow us to get an active credential using workflow
@@ -50,4 +52,7 @@ jobs:
project_id: 'internal-200822'
workload_identity_provider: 'projects/823469418460/locations/global/workloadIdentityPools/measurables-tracking/providers/angular'
service_account: 'measures-uploader@internal-200822.iam.gserviceaccount.com'
- run: pnpm ng-dev perf workflows --name ${{ matrix.workflow }} --commit-sha ${{github.sha}}
- run: pnpm ng-dev perf workflows --name "$WORKFLOW" --commit-sha "$COMMIT_SHA"
env:
WORKFLOW: ${{ matrix.workflow }}
COMMIT_SHA: ${{ github.sha }}
+25 -33
View File
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Check code lint
@@ -32,12 +32,14 @@ jobs:
run: pnpm ng-dev ngbot verify
- name: Confirm code builds with typescript as expected
run: pnpm check-tooling-setup
- name: Validate agent skills
run: pnpm ng-dev misc validate-skills
- name: Check commit message
run: pnpm ng-dev commit-message validate-range ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
- name: Check code format
run: pnpm ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
- name: Check Package Licenses
uses: angular/dev-infra/github-actions/linting/licenses@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/linting/licenses@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
@@ -45,13 +47,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
with:
disable-package-manager-cache: true
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run unit tests
@@ -59,7 +61,7 @@ jobs:
- name: Test build
run: pnpm devtools:build:chrome
- name: Cypress run
uses: cypress-io/github-action@84d178e4bbce871e23f2ffa3085898cde0e4f0ec # v7.1.2
uses: cypress-io/github-action@09090944bd8aaa2a517cefb6e38bf1aae336b42b # v7.4.3
with:
command: pnpm devtools:test:e2e
start: pnpm bazel run //devtools/src:devserver
@@ -71,11 +73,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run CI tests for framework
@@ -86,7 +88,7 @@ jobs:
ASPECT_RULES_JS_FROZEN_PNPM_LOCK: '1'
- name: Upload GRPC logs (for debugging of RBE issues)
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
path: /tmp/rbe-grpc.log
retention-days: 1
@@ -95,11 +97,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel Remote Caching
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run integration CI tests for framework
@@ -110,11 +112,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run tests
@@ -127,11 +129,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- name: Run tests
@@ -142,11 +144,11 @@ jobs:
labels: ubuntu-latest
steps:
- name: Initialize environment
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel
uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/setup@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Setup Bazel RBE
uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc
uses: angular/dev-infra/github-actions/bazel/configure-remote@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
- name: Install node modules
run: pnpm install --frozen-lockfile
- run: |
@@ -172,16 +174,6 @@ jobs:
- run: pnpm -C packages/zone.js jest:test
- run: pnpm -C packages/zone.js jest:nodetest
- run: pnpm -C packages/zone.js vitest:test
- run: pnpm -C packages/zone.js vitest-globals:test
- run: pnpm -C packages/zone.js electrontest
- run: pnpm -C packages/zone.js/test/typings test
# saucelabs:
# runs-on: ubuntu-latest
# env:
# SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
# steps:
# - name: Initialize environment
# uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b5a3609f89c06eb4037dce22a93641213a5d1508
# - name: Install node modules
# run: pnpm install --frozen-lockfile
# - uses: ./.github/actions/saucelabs-legacy
+24
View File
@@ -0,0 +1,24 @@
name: Publish Release
on:
push:
branches:
- main
- '[0-9]+.[0-9]+.x'
workflow_dispatch: # Allow manual trigger for verification
# Ensure only one release runs at a time PER BRANCH to avoid race conditions.
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read # Required to checkout the repository
id-token: write # Required for NPM provenance in reusable workflow
jobs:
release:
uses: angular/dev-infra/.github/workflows/reusable-release.yml@4a09f9588769980eacb41fcc76e2c76d048eac42 # main
secrets:
wombot-token: ${{ secrets.WOMBOT_TOKEN }}
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
-52
View File
@@ -1,52 +0,0 @@
name: OpenSSF Scorecard
on:
branch_protection_rule:
schedule:
- cron: '0 0 * * 0'
push:
branches: [main]
workflow_dispatch:
# Declare default permissions as read only.
permissions:
contents: read
jobs:
analysis:
name: Scorecards analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results
id-token: write
actions: read
contents: read
steps:
- name: 'Checkout code'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: 'Run analysis'
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
repo_token: ${{ secrets.GITHUB_TOKEN }}
publish_results: true
# Upload the results as artifacts.
- name: 'Upload artifact'
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
with:
sarif_file: results.sarif
+1 -1
View File
@@ -9,5 +9,5 @@ export const github = {
name: 'angular',
mainBranchName: 'main',
mergeMode: 'caretaker-only',
requireReleaseModeForRelease: true,
requireReleaseModeForRelease: false,
};
+1
View File
@@ -10,6 +10,7 @@
"packages/compiler-cli/private/bazel.ts",
"packages/compiler-cli/private/localize.ts",
"packages/compiler-cli/private/tooling.ts",
"packages/compiler-cli/private/hybrid_analysis.ts",
"packages/compiler-cli/private/babel.d.ts",
"packages/compiler-cli/src/bin/**",
"packages/core/schematics/utils/tsurge/helpers/angular_devkit/**",
+16 -2
View File
@@ -7,7 +7,14 @@ export const release = {
publishRegistry: 'https://wombat-dressing-room.appspot.com',
representativeNpmPackage: '@angular/core',
npmPackages: [
{name: '@angular/animations'},
{
name: '@angular/animations',
deprecated: {
version: '>=20.2.0-next.3',
message:
'@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.',
},
},
{name: '@angular/common'},
{name: '@angular/compiler-cli'},
{name: '@angular/compiler'},
@@ -17,7 +24,14 @@ export const release = {
{name: '@angular/language-server'},
{name: '@angular/language-service'},
{name: '@angular/localize'},
{name: '@angular/platform-browser-dynamic'},
{
name: '@angular/platform-browser-dynamic',
deprecated: {
version: '>=20.1.0-next.0',
message:
'@angular/platform-browser-dynamic is deprecated. Use `@angular/platform-browser` instead.',
},
},
{name: '@angular/platform-browser'},
{name: '@angular/platform-server'},
{name: '@angular/router'},
-1
View File
@@ -1,6 +1,5 @@
{
"compilerOptions": {
"strict": true,
"target": "es2020",
"module": "Node16",
"noEmit": true,
-12
View File
@@ -1,12 +0,0 @@
# Yarn Berry doesn't check engines at all, so pnpm shouldn't either.
engine-strict = false
# Disabling pnpm [hoisting](https://pnpm.io/npmrc#hoist) by setting `hoist=false` is recommended on
# projects using rules_js so that pnpm outside of Bazel lays out a node_modules tree similar to what
# rules_js lays out under Bazel (without a hidden node_modules/.pnpm/node_modules)
hoist=false
# Avoid pnpm auto-installing peer dependencies. We want to be explicit about our versions used
# for peer dependencies, avoiding potential mismatches. In addition, it ensures we can continue
# to rely on peer dependency placeholders substituted via Bazel.
auto-install-peers=false
+1 -1
View File
@@ -1 +1 @@
22.22.0
24.21.0
+1 -1
View File
@@ -53,7 +53,7 @@ function readPackage(pkg, context) {
if (pkg.version === '0.0.0-PLACEHOLDER' && localAngularPackages.has(key)) {
pkg.dependencies = {
...pkg.dependencies,
[key]: 'workspace: *',
[key]: 'workspace:*',
};
delete pkg.peerDependencies[key];
+7
View File
@@ -30,11 +30,18 @@ vscode-ng-language-service/syntaxes/test/data/*.html
# Ignore goldens MD files
goldens/**/*.api.md
# Ignore golden symbol json files
packages/**/*.golden_symbols.json
# adev generated files
adev/src/content/aria/**/*.json
adev/src/content/cli/**/*.json
adev/src/content/cdk/**/*.json
# Example package.json containing docregion (`// #docregion`) markers, which are
# not valid JSON and cannot be processed by Prettier's json-stringify parser.
adev/src/content/examples/schematics-for-libraries/projects/my-lib/package.json
# Antigravity rules
.agent/rules/agents.md
+38 -57
View File
@@ -36,8 +36,9 @@
version: 3
#availability:
# users_unavailable: []
availability:
users_unavailable:
- devversion
# Meta field that goes unused by PullApprove to allow for defining aliases to be
# used throughout the config.
@@ -99,14 +100,13 @@ groups:
reviewers:
users:
- ~alxhub
- AndrewKushnir
- ~AndrewKushnir
- atscott
- crisbeto
- devversion
- thePunderWoman
- ~thePunderWoman
- kirjs
- JoostK
- mmalerba
- ~amishne
- ~leonsenft
- ~mattrbeck
@@ -120,6 +120,7 @@ groups:
conditions:
- >
contains_any_globs(files.exclude('packages/core/primitives/*'), [
'.agent/skills/**/{*,.*}',
'contributing-docs/public-api-surface.md',
'dev-app/**/{*,.*}',
'integration/**/{*,.*}',
@@ -137,6 +138,7 @@ groups:
'packages/platform-browser/**/{*,.*}',
'packages/platform-browser-dynamic/**/{*,.*}',
'packages/platform-server/**/{*,.*}',
'packages/private/**/{*,.*}',
'packages/ssr/**/{*,.*}',
'packages/router/**/{*,.*}',
'packages/service-worker/**/{*,.*}',
@@ -146,14 +148,13 @@ groups:
reviewers:
users:
- ~alxhub
- AndrewKushnir
- ~AndrewKushnir
- atscott
- crisbeto
- devversion
- kirjs
- thePunderWoman
- ~thePunderWoman
- ~pkozlowski-opensource
- mmalerba
- JeanMeche
- ~amishne
- ~leonsenft
@@ -202,14 +203,14 @@ groups:
users:
- ~JiaLiPassion
- ~alxhub
- AndrewKushnir
- ~AndrewKushnir
- atscott
- crisbeto
- devversion
- kirjs
- thePunderWoman
- alan-agius4
- ~thePunderWoman
- ~pkozlowski-opensource
- mmalerba
- ~amishne
- ~leonsenft
- ~mattrbeck
@@ -246,24 +247,25 @@ groups:
- >
contains_any_globs(files, [
'adev/**/{*,.*}',
'tools/manual_api_docs/blocks/*.md',
'tools/manual_api_docs/elements/*.md',
])
reviewers:
users:
- alan-agius4
- ~alxhub
- AndrewKushnir
- ~AndrewKushnir
- atscott
- bencodezen
- crisbeto
- kirjs
- JeanMeche
- thePunderWoman
- ~thePunderWoman
- devversion
- josephperrott
- ~pkozlowski-opensource
- ~mgechev
- MarkTechson
- mmalerba
- ~hawkgs
- ~amishne
- ~leonsenft
@@ -284,13 +286,14 @@ groups:
reviewers:
users:
- AleksanderBodurri
- csmick
- ~devversion
- dgp1130
- eduhmc
- hawkgs
- hybrist
- ~josephperrott
- JeanMeche
- milomg
- ~josephperrott
- ~milomg
# =========================================================
# Dev-infra
@@ -299,7 +302,12 @@ groups:
<<: *defaults
conditions:
- >
contains_any_globs(files.exclude('.pullapprove.yml'), [
contains_any_globs(files
.exclude('.pullapprove.yml')
.exclude('tools/manual_api_docs/blocks/*.md')
.exclude('tools/manual_api_docs/elements/*.md')
.exclude('.agent/**/*.md'),
[
'{*,.*}',
'.agent/**/{*,.*}',
'.devcontainer/**/{*,.*}',
@@ -315,18 +323,14 @@ groups:
'modules/{*,.*}',
'packages/{*,.*}',
'packages/examples/test-utils/**/{*,.*}',
'packages/private/**/{*,.*}',
'packages/examples/{*,.*}',
'scripts/**/{*,.*}',
'third_party/**/{*,.*}',
'tools/contributing-stats/**/{*,.*}',
'tools/gulp-tasks/**/{*,.*}',
'tools/legacy-saucelabs/**/{*,.*}',
'tools/manual_api_docs/**/{*,.*}',
'tools/pnpm-patches/**/{*,.*}',
'tools/rxjs/**/{*,.*}',
'tools/saucelabs-daemon/**/{*,.*}',
'tools/saucelabs/**/{*,.*}',
'tools/symbol-extractor/**/{*,.*}',
'tools/testing/**/{*,.*}',
'tools/tslint/**/{*,.*}',
@@ -370,13 +374,12 @@ groups:
])
reviewers:
users:
- AndrewKushnir
- ~AndrewKushnir
- ~alxhub
- atscott
- thePunderWoman
- ~thePunderWoman
- ~pkozlowski-opensource
- kirjs
- mmalerba
- crisbeto
- devversion
- JeanMeche
@@ -407,12 +410,12 @@ groups:
reviewers:
users:
- ~alxhub
- AndrewKushnir
- ~AndrewKushnir
- atscott
- kirjs
- thePunderWoman
- JeanMeche
- ~thePunderWoman
- ~pkozlowski-opensource
- mmalerba
- ~amishne
- ~leonsenft
- ~mattrbeck
@@ -434,7 +437,7 @@ groups:
])
reviewers:
users:
- marktechson
- MarkTechson
- kirjs
- ~JeanMeche
- ~dgp1130
@@ -456,10 +459,10 @@ groups:
reviewers:
users:
- ~alxhub
- AndrewKushnir
- ~AndrewKushnir
- andrewseguin
- dgp1130
- thePunderWoman
- ~thePunderWoman
- josephperrott
# =========================================================
@@ -478,34 +481,12 @@ groups:
users:
- ~pkozlowski-opensource # Pawel Kozlowski
- ~alxhub # Alex Rickabaugh
- thePunderWoman # Jessica Janiuk
- AndrewKushnir # Andrew Kushnir
- ~thePunderWoman # Jessica Janiuk
- ~AndrewKushnir # Andrew Kushnir
- atscott # Andrew Scott
labels:
pending: 'requires: TGP'
approved: 'requires: TGP'
rejected: 'requires: TGP'
# External team required reviews
primitives-shared:
<<: *defaults
conditions:
- >
contains_any_globs(files, [
'packages/core/primitives/**/{*,.*}',
])
reviewers:
users:
- csmick # Cameron Smick
- mturco # Matt Turco
- iteriani # Thomas Nguyen
- tbondwilkinson # Tom Wilkinson
- rahatarmanahmed # Rahat Ahmed
- ENAML # Ethan Cline
labels:
pending: 'requires: TGP'
approved: 'requires: TGP'
rejected: 'requires: TGP'
- e-cline # Ethan Cline
- rockymeza # Rocky Meza
####################################################################################
# Override managed result groups
+1 -21
View File
@@ -1,4 +1,3 @@
load("@aspect_rules_js//js:defs.bzl", "js_library")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load("@devinfra//bazel/validation:defs.bzl", "validate_ts_version_matching")
load("@npm//:defs.bzl", "npm_link_all_packages")
@@ -8,8 +7,6 @@ package(default_visibility = ["//visibility:public"])
exports_files([
"LICENSE",
"karma-js.conf.js",
"browser-providers.conf.js",
"package.json",
])
@@ -25,7 +22,7 @@ filegroup(
)
validate_ts_version_matching(
module_lock_file = "MODULE.bazel.lock",
module_bazel = "MODULE.bazel",
package_json = "package.json",
)
@@ -34,14 +31,6 @@ alias(
actual = "//packages:tsconfig-build.json",
)
js_library(
name = "browser-providers",
srcs = [
"browser-providers.conf.d.ts",
"browser-providers.conf.js",
],
)
copy_to_bin(
name = "angularjs_scripts",
srcs = [
@@ -64,15 +53,6 @@ config_setting(
values = {"stamp": "true"},
)
alias(
name = "sauce_connect",
actual = select({
"@devinfra//bazel/constraints:linux_x64": "@sauce_connect_linux_amd64//:bin/sc",
"@devinfra//bazel/constraints:macos_x64": "@sauce_connect_mac//:bin/sc",
"@devinfra//bazel/constraints:macos_arm64": "@sauce_connect_mac//:bin/sc",
}),
)
# When enabled, this flag substitutes dependency versions with snapshot repositories
# for all packages in this repository. Note that this does not apply to peer
# dependencies, as they must be installed directly.
+1867 -117
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -4967,9 +4967,9 @@ To learn about the release highlights and our CLI-powered automated update workf
- **ivy:** i18n - render legacy message ids in `$localize` if requested ([#32937](https://github.com/angular/angular/issues/32937)) ([bcbf3e4](https://github.com/angular/angular/commit/bcbf3e4))
- **language-service:** module definitions on directive hover ([#32763](https://github.com/angular/angular/issues/32763)) ([0d186dd](https://github.com/angular/angular/commit/0d186dd)), closes [#32565](https://github.com/angular/angular/issues/32565)
- **ngcc:** expose `--create-ivy-entry-points` option on ivy-ngcc ([#33049](https://github.com/angular/angular/issues/33049)) ([b2b917d](https://github.com/angular/angular/commit/b2b917d)), closes [/github.com/angular/angular/pull/32999#issuecomment-539937368](https://github.com/angular/angular/pull/32999/issues/issuecomment-539937368)
- update rxjs peerDependencies minimum requirment to 6.5.3 ([#32812](https://github.com/angular/angular/issues/32812)) ([66658c4](https://github.com/angular/angular/commit/66658c4))
- update rxjs peerDependencies minimum requirement to 6.5.3 ([#32812](https://github.com/angular/angular/issues/32812)) ([66658c4](https://github.com/angular/angular/commit/66658c4))
- **ivy:** support ng-add in localize package ([#32791](https://github.com/angular/angular/issues/32791)) ([e41cbfb](https://github.com/angular/angular/commit/e41cbfb))
- **language-service:** allow retreiving synchronized analyzed NgModules ([#32779](https://github.com/angular/angular/issues/32779)) ([98feee7](https://github.com/angular/angular/commit/98feee7))
- **language-service:** allow retrieving synchronized analyzed NgModules ([#32779](https://github.com/angular/angular/issues/32779)) ([98feee7](https://github.com/angular/angular/commit/98feee7))
- **service-worker:** remove deprecated `versionedFiles` option ([#32862](https://github.com/angular/angular/issues/32862)) ([5d5c94d](https://github.com/angular/angular/commit/5d5c94d))
- **language-service:** expose determining the NgModule of a Directive ([#32710](https://github.com/angular/angular/issues/32710)) ([2846505](https://github.com/angular/angular/commit/2846505)), closes [#32565](https://github.com/angular/angular/issues/32565)
- **bazel:** support ts_library targets as entry-points for ng_package ([#32610](https://github.com/angular/angular/issues/32610)) ([217db9b](https://github.com/angular/angular/commit/217db9b))
@@ -5114,7 +5114,7 @@ To learn about the release highlights and our CLI-powered automated update workf
We assume you will fetch rules_nodejs in your WORKSPACE file, and no other dependencies remain here.
Simply remove any calls to this function and the corresponding load statement.
- typescript 3.4 and 3.5 are no longer supported, please update to typescript 3.6
- We no longer directly have a direct depedency on `tslib`. Instead it is now listed a `peerDependency`.
- We no longer directly have a direct dependency on `tslib`. Instead it is now listed a `peerDependency`.
Users not using the CLI will need to manually install `tslib` via;
@@ -6617,7 +6617,7 @@ For example:
- **forms:** properly handle special properties in FormGroup.get ([#22249](https://github.com/angular/angular/issues/22249)) ([dc3e8aa](https://github.com/angular/angular/commit/dc3e8aa)), closes [#17195](https://github.com/angular/angular/issues/17195)
- **platform-server:** avoid clash between server and client style encapsulation attributes ([#24158](https://github.com/angular/angular/issues/24158)) ([e9f2203](https://github.com/angular/angular/commit/e9f2203))
- **platform-server:** avoid dependency cycle when using http interceptor ([#24229](https://github.com/angular/angular/issues/24229)) ([2991b1b](https://github.com/angular/angular/commit/2991b1b)), closes [#23023](https://github.com/angular/angular/issues/23023)
- **platform-server:** don't reflect innerHTML property to attibute ([#24213](https://github.com/angular/angular/issues/24213)) ([c17098d](https://github.com/angular/angular/commit/c17098d)), closes [#19278](https://github.com/angular/angular/issues/19278)
- **platform-server:** don't reflect innerHTML property to attribute ([#24213](https://github.com/angular/angular/issues/24213)) ([c17098d](https://github.com/angular/angular/commit/c17098d)), closes [#19278](https://github.com/angular/angular/issues/19278)
- **platform-server:** provide Domino DOM types globally ([#24116](https://github.com/angular/angular/issues/24116)) ([906b3ec](https://github.com/angular/angular/commit/906b3ec)), closes [#23280](https://github.com/angular/angular/issues/23280) [#23133](https://github.com/angular/angular/issues/23133)
<!-- CHANGELOG SPLIT MARKER -->
@@ -9193,7 +9193,7 @@ Note: 4.0.0-beta.0 release also contains all the changes present in the 2.3.1 re
- **compiler:** support dotted property binding ([8db184d](https://github.com/angular/angular/commit/8db184d)), closes [angular/flex-layout#34](https://github.com/angular/flex-layout/issues/34)
- **compiler:** update to metadata version 3 ([#13464](https://github.com/angular/angular/issues/13464)) ([b9b557c](https://github.com/angular/angular/commit/b9b557c))
- **core:** detectChanges() doesn't work on detached instance ([4d6ac9d](https://github.com/angular/angular/commit/4d6ac9d)), closes [#13426](https://github.com/angular/angular/issues/13426) [#13472](https://github.com/angular/angular/issues/13472)
- **core:** properly destroy embedded Views attatched to ApplicationRef ([#13459](https://github.com/angular/angular/issues/13459)) ([d40bbf4](https://github.com/angular/angular/commit/d40bbf4)), closes [#13062](https://github.com/angular/angular/issues/13062)
- **core:** properly destroy embedded Views attached to ApplicationRef ([#13459](https://github.com/angular/angular/issues/13459)) ([d40bbf4](https://github.com/angular/angular/commit/d40bbf4)), closes [#13062](https://github.com/angular/angular/issues/13062)
- **core:** remove logError from logGroup ([#12925](https://github.com/angular/angular/issues/12925)) ([5fab871](https://github.com/angular/angular/commit/5fab871))
- **forms:** ensure `select[multiple]` retains selections ([b3dcff0](https://github.com/angular/angular/commit/b3dcff0)), closes [#12527](https://github.com/angular/angular/issues/12527) [#12654](https://github.com/angular/angular/issues/12654)
- **forms:** fix Validators.min/maxLength with FormArray ([#13095](https://github.com/angular/angular/issues/13095)) ([7383e4a](https://github.com/angular/angular/commit/7383e4a)), closes [#13089](https://github.com/angular/angular/issues/13089)
+2 -2
View File
@@ -71,7 +71,7 @@ You can file new issues by selecting from our [new issue templates](https://gith
### <a name="pr-quality"></a> Contribution Quality
We strongly value open source contribution and pull requests from community contributors. Please note that every pull request is reviewed and merged by an actual person on the team, which does take time and effort. That is time and effort that does take away from other valuable work. With that in mind we have an minimum set of expectations that are required of any community contribution pull request that is opened.
We strongly value open source contribution and pull requests from community contributors. Please note that every pull request is reviewed and merged by an actual person on the team, which does take time and effort. That is time and effort that does take away from other valuable work. With that in mind we have a minimum set of expectations that are required of any community contribution pull request that is opened.
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
- You don't want to duplicate existing efforts.
@@ -238,7 +238,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
- For corporations, we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
If you have more than one GitHub account, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
+41 -57
View File
@@ -4,43 +4,43 @@ module(
name = "angular",
)
bazel_dep(name = "rules_pkg", version = "1.2.0")
bazel_dep(name = "rules_nodejs", version = "6.7.3")
bazel_dep(name = "aspect_rules_ts", version = "3.8.4")
bazel_dep(name = "aspect_rules_js", version = "2.9.2")
bazel_dep(name = "aspect_rules_esbuild", version = "0.25.0")
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.2")
bazel_dep(name = "rules_pkg", version = "1.3.0")
bazel_dep(name = "rules_nodejs", version = "6.7.5")
bazel_dep(name = "aspect_rules_ts", version = "3.10.1")
bazel_dep(name = "aspect_rules_js", version = "3.4.1")
bazel_dep(name = "aspect_rules_esbuild", version = "0.27.0")
bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4")
bazel_dep(name = "aspect_rules_rollup", version = "2.0.1")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "aspect_bazel_lib", version = "2.22.5")
bazel_dep(name = "tar.bzl", version = "0.8.1")
bazel_dep(name = "yq.bzl", version = "0.3.4")
bazel_dep(name = "bazel_skylib", version = "1.9.2")
bazel_dep(name = "bazel_lib", version = "3.7.2")
bazel_dep(name = "tar.bzl", version = "0.10.8")
bazel_dep(name = "yq.bzl", version = "0.4.0")
bazel_dep(name = "rules_angular")
git_override(
module_name = "rules_angular",
commit = "d746c4f75e42cffe389d1ab077f4639be2bc78d1",
remote = "https://github.com/devversion/rules_angular.git",
commit = "5fa856469c642490a6e381a05d7f58f60fad1913",
remote = "https://github.com/angular/rules_angular.git",
)
bazel_dep(name = "devinfra")
git_override(
module_name = "devinfra",
commit = "7c08ac2a4f396bad752829fba09dbaefbcded9fc",
commit = "4a09f9588769980eacb41fcc76e2c76d048eac42",
remote = "https://github.com/angular/dev-infra.git",
)
bazel_dep(name = "rules_sass")
git_override(
module_name = "rules_sass",
commit = "1184a80751a21af8348f308abc5b38a41f26850e",
remote = "https://github.com/devversion/rules_sass.git",
commit = "bf9d6564f57b4df94b4915086ad0e7ad49a95f37",
remote = "https://github.com/angular/rules_sass.git",
)
bazel_dep(name = "rules_browsers")
git_override(
module_name = "rules_browsers",
commit = "e08ae33c679d07b3b2fcc136658b787a81995bc5",
remote = "https://github.com/devversion/rules_browsers.git",
commit = "c37398d63f5e990d618d02f4c6fb2fefe40f1a79",
remote = "https://github.com/angular/rules_browsers.git",
)
yq = use_extension("@yq.bzl//yq:extensions.bzl", "yq")
@@ -49,15 +49,15 @@ use_repo(yq, "yq_toolchains")
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
node.toolchain(
node_repositories = {
"22.22.0-darwin_arm64": ("node-v22.22.0-darwin-arm64.tar.gz", "node-v22.22.0-darwin-arm64", "5ed4db0fcf1eaf84d91ad12462631d73bf4576c1377e192d222e48026a902640"),
"22.22.0-darwin_amd64": ("node-v22.22.0-darwin-x64.tar.gz", "node-v22.22.0-darwin-x64", "5ea50c9d6dea3dfa3abb66b2656f7a4e1c8cef23432b558d45fb538c7b5dedce"),
"22.22.0-linux_arm64": ("node-v22.22.0-linux-arm64.tar.xz", "node-v22.22.0-linux-arm64", "1bf1eb9ee63ffc4e5d324c0b9b62cf4a289f44332dfef9607cea1a0d9596ba6f"),
"22.22.0-linux_ppc64le": ("node-v22.22.0-linux-ppc64le.tar.xz", "node-v22.22.0-linux-ppc64le", "d83b9957431cc18e1fc143a4b99f89cde7b8a18f53ef392231b4336afd058865"),
"22.22.0-linux_s390x": ("node-v22.22.0-linux-s390x.tar.xz", "node-v22.22.0-linux-s390x", "5aa0e520689448c4233e8d73f284e8e0634fdcd32b479735698494be5641f3e4"),
"22.22.0-linux_amd64": ("node-v22.22.0-linux-x64.tar.xz", "node-v22.22.0-linux-x64", "9aa8e9d2298ab68c600bd6fb86a6c13bce11a4eca1ba9b39d79fa021755d7c37"),
"22.22.0-windows_amd64": ("node-v22.22.0-win-x64.zip", "node-v22.22.0-win-x64", "c97fa376d2becdc8863fcd3ca2dd9a83a9f3468ee7ccf7a6d076ec66a645c77a"),
"24.21.0-darwin_arm64": ("node-v24.21.0-darwin-arm64.tar.gz", "node-v24.21.0-darwin-arm64", "bed7eea5325e1108f32ce5228ddd6a5f0f08a499ee42aa7442aea583702f6057"),
"24.21.0-darwin_amd64": ("node-v24.21.0-darwin-x64.tar.gz", "node-v24.21.0-darwin-x64", "1462cb3b3046b815cf8ea436d3da450ec1a9f11dac7e5a46b0ada5305d7e8097"),
"24.21.0-linux_arm64": ("node-v24.21.0-linux-arm64.tar.xz", "node-v24.21.0-linux-arm64", "6ad1325edbdb5649c379b75a237147a666c95d4f9ae8d340fef2d1575d289ad2"),
"24.21.0-linux_ppc64le": ("node-v24.21.0-linux-ppc64le.tar.xz", "node-v24.21.0-linux-ppc64le", "1936fd64623a2f98d1fb31b456686d10c30e92639899cfefdefa8835d22adccd"),
"24.21.0-linux_s390x": ("node-v24.21.0-linux-s390x.tar.xz", "node-v24.21.0-linux-s390x", "2ef7e2ecbf7a6c2f3d08d106f6b2f279419c6dac89fe91b8cad193af7890082c"),
"24.21.0-linux_amd64": ("node-v24.21.0-linux-x64.tar.xz", "node-v24.21.0-linux-x64", "fd8e59d5a511510f6a298afb548f18c7d2b1be404d8b4a27d94fbe49f56cb2d6"),
"24.21.0-windows_amd64": ("node-v24.21.0-win-x64.zip", "node-v24.21.0-win-x64", "158f7685b44de51f6c0df1d153526cbcd3e1bc739a8dfc607721cef75de9e541"),
},
node_version = "22.22.0",
node_version = "24.21.0",
)
use_repo(node, "nodejs_toolchains")
use_repo(node, "nodejs_darwin_amd64")
@@ -71,8 +71,8 @@ use_repo(node, "nodejs_windows_amd64")
pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm")
pnpm.pnpm(
name = "pnpm",
pnpm_version = "10.30.0",
pnpm_version_integrity = "sha512-K1dT3gFdSA7riPW1th4AUfBbQwGAioLsi4QMnSrfd0jrNSyD9cFZPKcD/xAXKVvD/dMRmruWhu/Ja5/LGCAJNw==",
pnpm_version = "11.24.0",
pnpm_version_integrity = "sha512-vSfjRel23LC+C3oSKCF7BJqBfiGx81XJDb59xGZxiVqLwebQbCRVRQXqk+oLRfSJon7Bv7yN5qlln8oPFvoAAA==",
)
use_repo(pnpm, "pnpm")
@@ -86,6 +86,7 @@ npm.npm_translate_lock(
"//adev:package.json",
"//adev/shared-docs:package.json",
"//adev/shared-docs/pipeline/api-gen:package.json",
"//devtools:package.json",
"//integration:package.json",
"//modules:package.json",
"//packages/animations:package.json",
@@ -109,7 +110,11 @@ npm.npm_translate_lock(
"//tools/bazel/rules_angular_store:package.json",
"//vscode-ng-language-service/integration/project:package.json",
],
npmrc = "//:.npmrc",
lifecycle_hooks = {
# sleep requires node-gyp rebuild but the native module is not needed in Bazel;
# disable the install hook to avoid failing builds when node-gyp is unavailable.
"sleep": [],
},
pnpm_lock = "//:pnpm-lock.yaml",
)
use_repo(npm, "npm")
@@ -117,22 +122,20 @@ use_repo(npm, "npm")
rules_ts_ext = use_extension("@aspect_rules_ts//ts:extensions.bzl", "ext")
rules_ts_ext.deps(
name = "angular_npm_typescript",
# Obtained by: curl --silent https://registry.npmjs.org/typescript/6.0.0-beta | jq -r '.dist.integrity'
ts_integrity = "sha512-CldZdztDpQRLM1HC6WDQjQkQN5Ub5zRau737a1diGh3lPmb9oRsaWHk1y5iqK0o7+1bNJ0oXfEGRkAogFZBL+Q==",
ts_version = "6.0.0-beta",
# Obtained by: curl --silent https://registry.npmjs.org/typescript/6.0.2 | jq -r '.dist.integrity'
ts_integrity = "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
ts_version = "6.0.3",
)
use_repo(rules_ts_ext, **{"npm_typescript": "angular_npm_typescript"})
# TODO: Figure out how to make ng_project update whenever the packages/core::pkg target changes.
rules_angular = use_extension("@rules_angular//setup:extensions.bzl", "rules_angular")
use_repo_rule("@rules_angular//setup:repositories.bzl", "configurable_deps_repo")(
name = "rules_angular_configurable_deps",
angular_compiler_cli = "@angular//:node_modules/@angular/compiler-cli",
typescript = "@angular//:node_modules/typescript",
rules_angular.setup(
name = "angular_rules_angular_configurable_deps",
angular_compiler_cli = "//:node_modules/@angular/compiler-cli",
typescript = "//:node_modules/typescript",
)
override_repo(rules_angular, "rules_angular_configurable_deps")
use_repo(rules_angular, rules_angular_configurable_deps = "angular_rules_angular_configurable_deps")
register_toolchains(
"@devinfra//bazel/git-toolchain:git_linux_toolchain",
@@ -160,22 +163,3 @@ cldr_xml_data(
"https://github.com/unicode-org/cldr/releases/download/release-%s/core.zip" % CLDR_VERSION: "d5ee2abac64158c04884a722f8ef4830ea22b6c74aac20185be2838db8eda788",
},
)
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Fetch sauce connect (tool to open Saucelabs tunnel for Saucelabs browser tests)
http_archive(
name = "sauce_connect_linux_amd64",
build_file_content = """exports_files(["bin/sc"], visibility = ["//visibility:public"])""",
sha256 = "26b9c3630f441b47854b6032f7eca6f1d88d3f62e50ee44c27015d71a5155c36",
strip_prefix = "sc-4.8.2-linux",
url = "https://saucelabs.com/downloads/sc-4.8.2-linux.tar.gz",
)
http_archive(
name = "sauce_connect_mac",
build_file_content = """exports_files(["bin/sc"], visibility = ["//visibility:public"])""",
sha256 = "28277ce81ef9ab84f5b87b526258920a8ead44789a5034346e872629bbf38089",
strip_prefix = "sc-4.8.2-osx",
url = "https://saucelabs.com/downloads/sc-4.8.2-osx.zip",
)
+326 -3598
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -67,7 +67,7 @@ Install the Angular CLI globally:
npm install -g @angular/cli
```
Create workspace:
Create a workspace:
```
ng new [PROJECT NAME]
+3 -1
View File
@@ -16,6 +16,7 @@ exports_files([
APPLICATION_FILES = [
"//adev/src/assets/images",
"//adev/src/assets/images/v21-event:v21-event-images",
"//adev/src/assets/images/v22-event:v22-event-images",
"//adev/src/assets/others",
"//adev/src/assets/previews",
"//adev/src/assets:tutorials",
@@ -70,7 +71,6 @@ APPLICATION_DEPS = [
":node_modules/fflate",
":node_modules/marked",
":node_modules/ngx-progressbar",
":node_modules/open-in-idx",
":node_modules/tailwindcss",
":node_modules/typescript",
":node_modules/@types/dom-navigation",
@@ -84,6 +84,7 @@ APPLICATION_DEPS = [
":node_modules/@algolia/client-common",
":node_modules/@algolia/requester-browser-xhr",
":node_modules/@algolia/requester-node-http",
":node_modules/beasties",
":node_modules/@lezer/css",
":node_modules/@lezer/html",
":node_modules/@lezer/lr",
@@ -97,6 +98,7 @@ APPLICATION_DEPS = [
":node_modules/@shikijs/langs",
":node_modules/@shikijs/engine-oniguruma",
":node_modules/@shikijs/core",
":node_modules/@shikijs/primitive",
":node_modules/@shikijs/engine-javascript",
":node_modules/@shikijs/types",
":node_modules/@shikijs/vscode-textmate",
+6 -9
View File
@@ -7,9 +7,7 @@
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss",
"standalone": true,
"changeDetection": "OnPush"
"style": "scss"
}
},
"root": ".",
@@ -33,7 +31,8 @@
"src/robots.txt",
"src/llms.txt",
"src/assets",
"src/assets/images/v21-event"
"src/assets/images/v21-event",
"src/assets/images/v22-event"
],
"styles": ["@angular/docs/styles/global-styles.scss", "./src/local-styles.scss"],
"scripts": [],
@@ -71,18 +70,16 @@
"buildTarget": "web-ui:build",
"headers": {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp"
"Cross-Origin-Embedder-Policy": "credentialless"
}
}
},
"test": {
"builder": "@angular/build:unit-test",
"options": {
"options": {
"runner": "karma",
"browsers": ["ChromeHeadlessNoSandbox"],
"include": [
"src/app/**/*.spec.ts"
]
"include": ["src/app/**/*.spec.ts"]
}
}
}
+2 -2
View File
@@ -49,7 +49,7 @@
"headers": [
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
"value": "credentialless"
}
]
},
@@ -71,7 +71,7 @@
},
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
"value": "credentialless"
}
]
}
+55 -54
View File
@@ -1,104 +1,105 @@
{
"dependencies": {
"@algolia/client-common": "5.48.0",
"@algolia/client-search": "5.48.0",
"@algolia/requester-browser-xhr": "5.48.0",
"@algolia/requester-node-http": "5.48.0",
"@algolia/client-common": "5.57.0",
"@algolia/client-search": "5.57.0",
"@algolia/requester-browser-xhr": "5.57.0",
"@algolia/requester-node-http": "5.57.0",
"@angular/animations": "workspace:*",
"@angular/aria": "21.2.0-rc.0",
"@angular/build": "21.2.0-next.2",
"@angular/cdk": "21.2.0-rc.0",
"@angular/cli": "21.2.0-next.2",
"@angular/aria": "22.2.0-next.5",
"@angular/build": "22.2.0-next.7",
"@angular/cdk": "22.2.0-next.5",
"@angular/cli": "22.2.0-next.7",
"@angular/common": "workspace:*",
"@angular/compiler": "workspace:*",
"@angular/compiler-cli": "workspace:*",
"@angular/core": "workspace:*",
"@angular/docs": "workspace:*",
"@angular/forms": "workspace:*",
"@angular/material": "21.2.0-rc.0",
"@angular/material": "22.2.0-next.5",
"@angular/platform-browser": "workspace:*",
"@angular/platform-server": "workspace:*",
"@angular/router": "workspace:*",
"@angular/ssr": "21.2.0-next.2",
"@codemirror/autocomplete": "6.20.0",
"@codemirror/commands": "6.10.1",
"@angular/ssr": "22.2.0-next.7",
"@codemirror/autocomplete": "6.20.3",
"@codemirror/commands": "6.11.0",
"@codemirror/lang-angular": "0.1.4",
"@codemirror/lang-css": "6.3.1",
"@codemirror/lang-html": "6.4.11",
"@codemirror/lang-javascript": "6.2.4",
"@codemirror/lang-html": "6.4.12",
"@codemirror/lang-javascript": "6.2.5",
"@codemirror/lang-sass": "6.0.2",
"@codemirror/language": "6.12.1",
"@codemirror/lint": "6.9.3",
"@codemirror/search": "6.6.0",
"@codemirror/state": "6.5.4",
"@codemirror/view": "6.39.12",
"@lezer/common": "1.5.1",
"@lezer/css": "1.3.0",
"@codemirror/language": "6.12.4",
"@codemirror/lint": "6.9.7",
"@codemirror/search": "6.7.1",
"@codemirror/state": "6.7.1",
"@codemirror/view": "6.43.9",
"@lezer/common": "1.5.2",
"@lezer/css": "1.3.6",
"@lezer/highlight": "1.2.3",
"@lezer/html": "1.3.13",
"@lezer/javascript": "1.5.4",
"@lezer/lr": "1.4.8",
"@lezer/lr": "1.4.10",
"@lezer/sass": "1.1.0",
"@marijn/find-cluster-break": "1.0.2",
"@shikijs/core": "^3.21.0",
"@shikijs/engine-javascript": "^3.21.0",
"@shikijs/engine-oniguruma": "^3.21.0",
"@shikijs/langs": "^3.21.0",
"@shikijs/themes": "^3.21.0",
"@shikijs/types": "^3.21.0",
"@marijn/find-cluster-break": "1.0.4",
"@shikijs/core": "^4.0.0",
"@shikijs/engine-javascript": "^4.0.0",
"@shikijs/engine-oniguruma": "^4.0.0",
"@shikijs/langs": "^4.0.0",
"@shikijs/primitive": "^4.0.0",
"@shikijs/themes": "^4.0.0",
"@shikijs/types": "^4.0.0",
"@shikijs/vscode-textmate": "^10.0.2",
"@stackblitz/sdk": "1.11.0",
"@types/dom-navigation": "1.0.6",
"@stackblitz/sdk": "1.11.1",
"@types/dom-navigation": "1.0.7",
"@types/jasmine": "6.0.0",
"@types/jsdom": "27.0.0",
"@types/node": "24.10.11",
"@typescript/vfs": "1.6.2",
"@webcontainer/api": "1.6.1",
"@types/jsdom": "30.0.0",
"@types/node": "24.13.3",
"@typescript/vfs": "1.6.4",
"@webcontainer/api": "1.6.4",
"@xterm/addon-fit": "0.11.0",
"@xterm/xterm": "6.0.0",
"algoliasearch": "5.48.0",
"algoliasearch": "5.57.0",
"angular-split": "20.0.0",
"beasties": "0.5.4",
"ccount": "^2.0.1",
"character-entities-html4": "^2.1.0",
"character-entities-legacy": "^3.0.0",
"comma-separated-tokens": "^2.0.3",
"crelt": "1.0.6",
"diff": "8.0.3",
"crelt": "1.0.7",
"diff": "9.0.0",
"emoji-regex": "10.6.0",
"fflate": "0.8.2",
"fflate": "0.8.3",
"hast-util-to-html": "^9.0.5",
"hast-util-whitespace": "^3.0.0",
"html-void-elements": "^3.0.0",
"jsdom": "28.0.0",
"jasmine-core": "6.0.0",
"jasmine-core": "6.3.0",
"jsdom": "30.0.1",
"karma-chrome-launcher": "3.2.0",
"karma-coverage": "2.2.1",
"karma-jasmine": "5.1.0",
"karma-jasmine-html-reporter": "2.2.0",
"marked": "17.0.1",
"mermaid": "11.12.2",
"karma-jasmine-html-reporter": "2.3.0",
"marked": "18.0.11",
"mermaid": "11.17.2",
"ngx-progressbar": "14.0.0",
"open-in-idx": "0.1.1",
"playwright-core": "1.58.1",
"preact": "10.28.3",
"preact-render-to-string": "6.6.5",
"prettier": "3.8.1",
"playwright-core": "1.62.1",
"preact": "10.29.8",
"preact-render-to-string": "6.7.0",
"prettier": "3.9.6",
"property-information": "^7.1.0",
"rxjs": "7.8.2",
"shiki": "3.22.0",
"shiki": "4.4.3",
"space-separated-tokens": "^2.0.2",
"stringify-entities": "^4.0.4",
"style-mod": "4.1.3",
"tinyglobby": "0.2.15",
"tinyglobby": "0.2.17",
"tslib": "2.8.1",
"typescript": "6.0.0-beta",
"typescript": "6.0.3",
"w3c-keyname": "2.2.8",
"zwitch": "^2.0.4"
},
"devDependencies": {
"autoprefixer": "10.4.24",
"autoprefixer": "10.5.4",
"karma": "~6.4.4",
"postcss": "8.5.6",
"postcss": "8.5.26",
"tailwindcss": "3.4.19"
}
}
+8
View File
@@ -29,6 +29,7 @@ ts_project(
deps = [
"//adev:node_modules/@angular/docs",
"//adev:node_modules/@types/node",
"//adev/shared-docs/pipeline/shared:heading",
"//adev/src/app/routing/navigation-entries",
"//adev/src/content/reference/errors:route-nav-items",
"//adev/src/content/reference/extended-diagnostics:route-nav-items",
@@ -50,4 +51,11 @@ js_run_binary(
outs = ["defined-routes.json"],
chdir = package_name(),
tool = ":generate_route",
# Public so the api-gen rendering pipeline (used from //packages/...) can validate guide
# links against the same set of routes defined for the live site.
visibility = [
"//adev:__subpackages__",
"//packages:__subpackages__",
"//tools:__subpackages__",
],
)
+21 -29
View File
@@ -7,6 +7,7 @@
*/
import {ALL_ITEMS} from '../../src/app/routing/navigation-entries/index.js';
import {extractHeadingIds, findDuplicateIds} from '../../shared-docs/pipeline/shared/heading.mjs';
import {NavigationItem} from '@angular/docs';
import {writeFileSync, readFileSync} from 'fs';
import {join, resolve} from 'path';
@@ -19,7 +20,7 @@ const contentRoot = resolve(process.cwd(), '../../src/content');
* in a JSON file. This file then used by other bazel targets to know which routes are valid.
*/
function extractRoutes(items: NavigationItem[]): string[] {
function extractRoutes(items: NavigationItem[], duplicatesByPage: Map<string, string[]>): string[] {
const routes: string[] = [];
for (const item of items) {
if (item.path && !item.path.startsWith('http')) {
@@ -28,7 +29,11 @@ function extractRoutes(items: NavigationItem[]): string[] {
const content = readFileSync(join(contentRoot, `${item.contentPath}.md`), {
encoding: 'utf-8',
});
const headings = extractHeadings(content);
const headings = extractHeadingIds(content);
const duplicates = findDuplicateIds(headings);
if (duplicates.length > 0) {
duplicatesByPage.set(`${item.contentPath}.md`, duplicates);
}
routes.push(
...headings.map(
(heading) => `${item.path}#${heading.toLowerCase().replace(/\s+/g, '-')}`,
@@ -37,33 +42,28 @@ function extractRoutes(items: NavigationItem[]): string[] {
}
}
if (item.children) {
routes.push(...extractRoutes(item.children));
routes.push(...extractRoutes(item.children, duplicatesByPage));
}
}
return routes;
}
function extractHeadings(content: string): string[] {
const headings = content
.split('\n')
// Top level heading (H1) are used for the page title only
// and yes, headings can have leading spaces
.filter((line) => line.trim().startsWith('##'))
.map((line) => line.replace(/^#+\s*/, '').trim());
const stepRegex = /<docs-step[^>]*title="([^"]*)"/g;
let match;
while ((match = stepRegex.exec(content)) !== null) {
headings.push(match[1]);
}
return headings.map((heading: string) => getIdFromHeading(heading));
}
function main() {
const allRoutes: string[] = [];
const duplicatesByPage = new Map<string, string[]>();
allRoutes.push(...extractRoutes(ALL_ITEMS));
allRoutes.push(...extractRoutes(ALL_ITEMS, duplicatesByPage));
if (duplicatesByPage.size > 0) {
const details = Array.from(duplicatesByPage)
.map(([page, ids]) => ` ${page}: ${ids.map((id) => `#${id}`).join(', ')}`)
.join('\n');
throw new Error(
`Headings must produce a unique anchor id within a page, otherwise every link to the ` +
`anchor resolves to the first heading that claims it. Give the later heading its own ` +
`id with the \`{#custom-id}\` syntax.\n${details}`,
);
}
const uniqueRoutes = Array.from(new Set(allRoutes.filter((r) => !!r)));
@@ -72,11 +72,3 @@ function main() {
}
main();
// TODO: refactor so this function is shared with the generation pipeline (adev/shared-docs/pipeline/shared/marked/transformations/heading.mts)
function getIdFromHeading(heading: string): string {
return heading
.toLowerCase()
.replace(/\s|\//g, '-') // replace spaces and slashes with dashes
.replace(/[^\p{L}\d\-]/gu, ''); // only keep letters, digits & dashes
}
-1
View File
@@ -2,7 +2,6 @@
"compileOnSave": false,
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
@@ -10,6 +10,8 @@ import {get} from 'node:https';
import {posix} from 'node:path';
const GITHUB_API = 'https://api.github.com/repos/';
const SHA_REGEX = /^[0-9a-f]{40}$/i;
const BRANCH_REGEX = /^(?!.*\.\.)[a-zA-Z0-9/_.-]+$/;
export class GithubClient {
#token;
@@ -30,6 +32,12 @@ export class GithubClient {
* @returns Promise<string[]>
*/
async getAffectedFiles(baseSha, headSha) {
if (!SHA_REGEX.test(baseSha)) {
throw new Error(`Invalid base SHA: ${baseSha}`);
}
if (!SHA_REGEX.test(headSha)) {
throw new Error(`Invalid head SHA: ${headSha}`);
}
const {files} = JSON.parse(await this.#httpGet(`${this.#api}/compare/${baseSha}...${headSha}`));
return files.map((f) => f.filename);
}
@@ -41,6 +49,9 @@ export class GithubClient {
* @returns Promise<string>
*/
async getShaForBranch(branch) {
if (!BRANCH_REGEX.test(branch)) {
throw new Error(`Invalid branch name: ${branch}`);
}
const sha = await this.#httpGet(`${this.#api}/commits/${branch}`, {
headers: {Accept: 'application/vnd.github.VERSION.sha'},
});
@@ -49,7 +60,7 @@ export class GithubClient {
throw new Error(`Unable to extract the SHA for '${branch}'.`);
}
return sha;
return sha.trim();
}
#httpGet(url, options = {}) {
@@ -8,7 +8,7 @@
//tslint:disable:no-console
import assert from 'node:assert';
import {execSync} from 'node:child_process';
import {execFileSync} from 'node:child_process';
import {existsSync, constants as fsConstants} from 'node:fs';
import {
copyFile,
@@ -41,6 +41,16 @@ export async function updateAssets({repo, assetsPath, destPath}) {
await readFile(buildInfoPath, 'utf-8'),
);
const shaRegex = /^[0-9a-f]{40}$/i;
const branchRegex = /^(?!.*\.\.)[a-zA-Z0-9/_.-]+$/;
if (!shaRegex.test(storedSha)) {
throw new Error(`Invalid SHA in build info: ${storedSha}`);
}
if (!branchRegex.test(storedBranch)) {
throw new Error(`Invalid branch name in build info: ${storedBranch}`);
}
assert(process.env.ANGULAR_READONLY_GITHUB_TOKEN);
const githubApi = new GithubClient(
repo,
@@ -63,6 +73,10 @@ export async function updateAssets({repo, assetsPath, destPath}) {
downstreamBranch = storedBranch;
}
if (!shaRegex.test(latestSha)) {
throw new Error(`Invalid SHA resolved: ${latestSha}`);
}
console.log(`Comparing ${storedSha}...${latestSha}.`);
const affectedFiles = await githubApi.getAffectedFiles(storedSha, latestSha);
const changedFiles = affectedFiles.filter((file) => file.startsWith(`${assetsPath}/`));
@@ -78,14 +92,18 @@ export async function updateAssets({repo, assetsPath, destPath}) {
try {
const execOptions = {cwd: temporaryDir, stdio: 'inherit'};
execSync('git init', execOptions);
execSync(`git remote add origin https://github.com/${repo}.git`, execOptions);
execFileSync('git', ['init'], execOptions);
execFileSync(
'git',
['remote', 'add', 'origin', `https://github.com/${repo}.git`],
execOptions,
);
// fetch a commit
execSync(`git fetch origin ${latestSha}`, execOptions);
execFileSync('git', ['fetch', 'origin', latestSha], execOptions);
// reset this repository's main branch to the commit of interest
execSync('git reset --hard FETCH_HEAD', execOptions);
execFileSync('git', ['reset', '--hard', 'FETCH_HEAD'], execOptions);
// get sha when files where changed
shaWhenFilesChanged = execSync(`git rev-list -1 ${latestSha} "${assetsPath}/"`, {
shaWhenFilesChanged = execFileSync('git', ['rev-list', '-1', latestSha, `${assetsPath}/`], {
encoding: 'utf8',
cwd: temporaryDir,
stdio: ['ignore', 'pipe', 'ignore'],
@@ -6,11 +6,10 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {Component} from '@angular/core';
@Component({
selector: 'docs-algolia-icon',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './algolia-icon.component.html',
})
export class AlgoliaIcon {}
@@ -6,17 +6,16 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ChangeDetectionStrategy, Component, inject, computed} from '@angular/core';
import {NavigationState} from '../../services/index';
import {NavigationItem} from '../../interfaces/index';
import {Component, computed, inject} from '@angular/core';
import {RouterLink} from '@angular/router';
import {NavigationItem} from '../../interfaces/index';
import {NavigationState} from '../../services/index';
@Component({
selector: 'docs-breadcrumb',
imports: [RouterLink],
templateUrl: './breadcrumb.component.html',
styleUrls: ['./breadcrumb.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class Breadcrumb {
private readonly navigationState = inject(NavigationState);
@@ -1,8 +1,16 @@
@if (!hasAccepted()) {
<div class="docs-cookies-popup docs-invert-mode">
<p>This site uses cookies from Google to deliver its services and to analyze traffic.</p>
<div class="docs-cookies-popup-header">
<img
class="docs-cookies-popup-angie"
src="assets/images/angie/greeting.svg"
alt=""
aria-hidden="true"
/>
<p>This site uses cookies from Google to deliver its services and to analyze traffic.</p>
</div>
<div>
<div class="docs-cookies-popup-actions">
<a
href="https://policies.google.com/technologies/cookies"
target="_blank"
@@ -15,15 +15,34 @@
border-radius: 0.25rem;
font-size: 0.875rem;
max-width: 265px;
transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
transition:
background-color 0.3s ease,
border-color 0.3s ease,
color 0.3s ease;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
> div {
.docs-cookies-popup-header {
display: flex;
gap: 0.75rem;
align-items: center;
}
.docs-cookies-popup-angie {
flex-shrink: 0;
width: 52px;
height: auto;
}
.docs-cookies-popup-actions {
display: flex;
gap: 0.5rem;
align-items: center;
width: 100%;
margin-block-start: 1rem;
.docs-primary-btn {
flex: 1;
}
}
p {
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core';
import {Component, inject, signal} from '@angular/core';
import {LOCAL_STORAGE} from '../../providers/index';
import {setCookieConsent} from '../../utils';
@@ -21,7 +21,6 @@ export const STORAGE_KEY = 'docs-accepts-cookies';
selector: 'docs-cookie-popup',
templateUrl: './cookie-popup.component.html',
styleUrls: ['./cookie-popup.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CookiePopup {
private readonly localStorage = inject(LOCAL_STORAGE);
@@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ChangeDetectionStrategy, Component, inject, input, signal} from '@angular/core';
import {Clipboard} from '@angular/cdk/clipboard';
import {Component, inject, input, signal} from '@angular/core';
import {MatTooltip} from '@angular/material/tooltip';
import {IconComponent} from '../icon/icon.component';
@@ -15,7 +15,7 @@ export const CONFIRMATION_DISPLAY_TIME_MS = 1000;
@Component({
selector: 'docs-copy-link-button',
template: `<docs-icon>{{ showCopySuccess() ? 'check' : 'link' }}</docs-icon>`,
template: `<docs-icon></docs-icon>`,
styles: `
:host {
cursor: pointer;
@@ -31,6 +31,13 @@ export const CONFIRMATION_DISPLAY_TIME_MS = 1000;
:host(.docs-copy-link-success) {
color: var(--bright-blue);
}
docs-icon::before {
content: '\\e250'; /* codepoint for "link" */
font-family: 'Material Symbols Outlined';
}
:host(.docs-copy-link-success) docs-icon::before {
content: '\\e668'; /* codepoint for "check" */
}
`,
hostDirectives: [
{
@@ -45,7 +52,6 @@ export const CONFIRMATION_DISPLAY_TIME_MS = 1000;
'[class.docs-copy-link-success]': 'showCopySuccess()',
},
imports: [IconComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CopyLinkButton {
readonly href = input.required<string>();
@@ -8,13 +8,13 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {Clipboard} from '@angular/cdk/clipboard';
import {Component, signal} from '@angular/core';
import {By} from '@angular/platform-browser';
import {
CONFIRMATION_DISPLAY_TIME_MS,
CopySourceCodeButton,
} from './copy-source-code-button.component';
import {ChangeDetectionStrategy, Component, signal} from '@angular/core';
import {By} from '@angular/platform-browser';
import {Clipboard} from '@angular/cdk/clipboard';
const SUCCESSFULLY_COPY_CLASS_NAME = 'docs-copy-source-code-button-success';
const FAILED_COPY_CLASS_NAME = 'docs-copy-source-code-button-failed';
@@ -99,7 +99,6 @@ describe('CopySourceCodeButton', () => {
<button docs-copy-source-code></button>
`,
imports: [CopySourceCodeButton],
changeDetection: ChangeDetectionStrategy.OnPush,
})
class CodeSnippetWrapper {
code = signal('');
@@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {Clipboard} from '@angular/cdk/clipboard';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
@@ -15,7 +15,6 @@ import {
inject,
signal,
} from '@angular/core';
import {Clipboard} from '@angular/cdk/clipboard';
import {IconComponent} from '../icon/icon.component';
export const REMOVED_LINE_CLASS_NAME = '.line.remove';
@@ -33,7 +32,6 @@ export const CONFIRMATION_DISPLAY_TIME_MS = 2000;
'[class.docs-copy-source-code-button-success]': 'showCopySuccess()',
'[class.docs-copy-source-code-button-failed]': 'showCopyFailure()',
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CopySourceCodeButton {
private readonly changeDetector = inject(ChangeDetectorRef);
@@ -7,18 +7,10 @@
*/
import {DOCUMENT} from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
afterNextRender,
computed,
inject,
signal,
} from '@angular/core';
import {Component, afterNextRender, computed, inject, signal} from '@angular/core';
@Component({
selector: 'docs-icon',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'material-symbols-outlined',
'[style.font-size.px]': 'fontSize()',
@@ -24,6 +24,7 @@ ng_project(
"//adev/shared-docs/interfaces",
"//adev/shared-docs/pipes",
"//adev/shared-docs/services",
"//adev/shared-docs/utils",
],
)
@@ -9,11 +9,17 @@
>
@for (itemGroup of groupItems(navigationItems, preserveOtherCategoryOrder); track $index) {
@let groupLabel = itemGroup[0];
@let items = itemGroup[1];
@let group = itemGroup[1];
@let items = group.items;
@let firstItem = items[0];
@if (groupLabel && collapsableLevel() !== firstItem.level && items.length > 1) {
<li class="docs-navigation-group">{{ groupLabel }}</li>
<li class="docs-navigation-group">
<span>{{ groupLabel }}</span>
<ng-container
*ngTemplateOutlet="itemStatus; context: {$implicit: {status: group.status}}"
/>
</li>
}
@for (item of items; track $index) {
<li
@@ -27,7 +33,7 @@
[href]="item.path"
target="_blank"
[matTooltip]="item.label"
[matTooltipDisabled]="itemLabel.length < 27"
[matTooltipDisabled]="isMobile || itemLabel.length < labelTruncationThreshold"
matTooltipPosition="after"
[attr.aria-label]="item.label"
[matTooltipClass]="'API-tooltip'"
@@ -53,9 +59,9 @@
matrixParams: 'ignored',
fragment: 'ignored',
}"
(click)="emitClickOnLink()"
(click)="emitClickOnLink(item)"
[matTooltip]="item.label"
[matTooltipDisabled]="itemLabel.length < 27"
[matTooltipDisabled]="isMobile || itemLabel.length < labelTruncationThreshold"
matTooltipPosition="after"
[attr.aria-label]="item.label"
[matTooltipClass]="'API-tooltip'"
@@ -76,7 +82,7 @@
<div
class="docs-secondary-nav-header"
[matTooltip]="item.label"
[matTooltipDisabled]="itemLabel.length < 27"
[matTooltipDisabled]="isMobile || itemLabel.length < labelTruncationThreshold"
matTooltipPosition="after"
[attr.aria-label]="item.label"
[matTooltipClass]="'API-tooltip'"
@@ -106,7 +112,7 @@
item.children && item.level === expandableLevel() && !item.isExpanded
"
[matTooltip]="item.label"
[matTooltipDisabled]="itemLabel.length < 27"
[matTooltipDisabled]="isMobile || itemLabel.length < labelTruncationThreshold"
matTooltipPosition="after"
[attr.aria-label]="item.label"
[matTooltipClass]="'API-tooltip'"
@@ -6,7 +6,7 @@
list-style: none;
overflow-y: auto;
overflow-x: hidden;
height: 100vh;
height: 100dvh;
padding: 0;
margin: 0;
padding-block: 1.5rem;
@@ -162,11 +162,12 @@ a,
}
}
.docs-external-link {
.docs-external-link.docs-faceted-list-item-text {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
max-width: 100%;
gap: 0.5rem;
&::after {
content: 'open_in_new';
@@ -174,7 +175,11 @@ a,
font-size: 1.1rem;
color: var(--quinary-contrast);
transition: color 0.3s ease;
margin-inline-end: 0.4rem;
margin-inline-end: 0.2rem;
}
a:hover &::after {
color: var(--primary-contrast);
}
}
@@ -188,8 +193,12 @@ a,
}
.docs-navigation-group {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0.5rem 0.5rem 1rem;
background: var(--septenary-contrast);
&:not(:first-child) {
margin-top: 2rem;
}
@@ -31,6 +31,32 @@ const navigationItems: NavigationItem[] = [
},
];
const navigationItemsWithCategoryStatus: NavigationItem[] = [
{
label: 'Forms',
level: 1,
categoriesStatus: [{'Signal Forms': 'new'}],
children: [],
},
];
navigationItemsWithCategoryStatus[0].children = [
{
label: 'Overview',
path: 'guide/forms',
level: 2,
category: 'Signal Forms',
parent: navigationItemsWithCategoryStatus[0],
},
{
label: 'Signals',
path: 'guide/forms/signals',
level: 2,
category: 'Signal Forms',
parent: navigationItemsWithCategoryStatus[0],
},
];
describe('NavigationList', () => {
let component: NavigationList;
let fixture: ComponentFixture<NavigationList>;
@@ -58,6 +84,20 @@ describe('NavigationList', () => {
expect(nonClickableItem.length).toBe(1);
});
it('should show category status on grouped navigation headers', async () => {
fixture.componentRef.setInput('navigationItems', [...navigationItemsWithCategoryStatus]);
await fixture.whenStable();
const categoryGroup = fixture.debugElement.query(By.css('.docs-navigation-group'));
const categoryStatus = fixture.debugElement.query(
By.css('.docs-navigation-group .docs-new-item'),
);
expect(categoryGroup.nativeElement.innerText).toContain('Signal Forms');
expect(categoryStatus).toBeTruthy();
expect(categoryStatus.nativeElement.innerText).toBe('New');
});
it('should append `docs-navigation-list-dropdown` when isDropdownView is true', async () => {
fixture.componentRef.setInput('isDropdownView', true);
await fixture.whenStable();
@@ -153,5 +193,6 @@ describe('NavigationList', () => {
class FakeNavigationListState {
isOpened = signal(true);
activeNavigationItem = signal(navigationItems.at(1));
crossCategoryOrigin = signal<NavigationItem | undefined>(undefined);
toggleItem(item: NavigationItem) {}
}
@@ -7,12 +7,13 @@
*/
import {NgTemplateOutlet} from '@angular/common';
import {ChangeDetectionStrategy, Component, inject, input, output} from '@angular/core';
import {Component, inject, input, output} from '@angular/core';
import {MatTooltip} from '@angular/material/tooltip';
import {RouterLink, RouterLinkActive} from '@angular/router';
import {NavigationItem} from '../../interfaces/index';
import {IsActiveNavigationItem} from '../../pipes';
import {NavigationState} from '../../services/index';
import {isMobile} from '../../utils';
import {IconComponent} from '../icon/icon.component';
@Component({
@@ -27,7 +28,6 @@ import {IconComponent} from '../icon/icon.component';
],
templateUrl: './navigation-list.component.html',
styleUrls: ['./navigation-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NavigationList {
readonly navigationItems = input.required<NavigationItem[]>();
@@ -39,10 +39,15 @@ export class NavigationList {
readonly linkClicked = output<void>();
protected readonly labelTruncationThreshold = 27;
private readonly navigationState = inject(NavigationState);
private readonly crossCategoryOrigin = this.navigationState.crossCategoryOrigin;
readonly activeItem = this.navigationState.activeNavigationItem;
protected readonly isMobile = isMobile;
toggle(item: NavigationItem): void {
if (
item.level === 1 &&
@@ -51,10 +56,19 @@ export class NavigationList {
) {
return;
}
const prevParentItem = this.crossCategoryOrigin();
if (prevParentItem) {
this.crossCategoryOrigin.set(undefined);
this.navigationState.toggleItem(prevParentItem);
return;
}
this.navigationState.toggleItem(item);
}
emitClickOnLink(): void {
emitClickOnLink(item: NavigationItem): void {
if (item.isCrossReferenced) {
this.crossCategoryOrigin.set(item.parent);
}
this.linkClicked.emit();
}
@@ -62,14 +76,27 @@ export class NavigationList {
return items.some((item) => !!item.category);
}
private getCategoryStatus(item: NavigationItem, category: string): 'new' | 'updated' | undefined {
const categoriesStatus = item.parent?.categoriesStatus;
if (!categoriesStatus) {
return undefined;
}
return categoriesStatus.find((status) => status[category])?.[category];
}
protected groupItems(
items: NavigationItem[],
preserveOtherCategoryOrder: boolean,
): Map<string, NavigationItem[]> {
): Map<string, {items: NavigationItem[]; status: 'new' | 'updated' | undefined}> {
const hasCategories = this.hasCategories(items);
if (hasCategories) {
const others: NavigationItem[] = [];
const categorizedItems = new Map<string, NavigationItem[]>();
const categorizedItems = new Map<
string,
{items: NavigationItem[]; status: 'new' | 'updated' | undefined}
>();
for (const item of items) {
const category = item.category || 'Other';
if (!preserveOtherCategoryOrder && category === 'Other') {
@@ -77,16 +104,20 @@ export class NavigationList {
continue;
}
if (!categorizedItems.has(category)) {
categorizedItems.set(category, []);
categorizedItems.set(category, {
items: [],
status: this.getCategoryStatus(item, category),
});
}
categorizedItems.get(category)!.push(item);
categorizedItems.get(category)!.items.push(item);
}
if (others.length) {
categorizedItems.set('Other', others);
categorizedItems.set('Other', {items: others, status: undefined});
}
return categorizedItems;
} else {
return new Map([['', items]]);
return new Map([['', {items, status: undefined}]]);
}
}
}
@@ -29,6 +29,7 @@ ng_project(
"//adev/shared-docs/pipes",
"//adev/shared-docs/providers",
"//adev/shared-docs/services",
"//adev/shared-docs/utils",
],
)
@@ -1,4 +1,4 @@
<dialog #searchDialog>
<dialog #searchDialog id="docsSearchDialog">
<div class="docs-search-container" (docsClickOutside)="closeSearchDialog()">
<docs-text-field
[autofocus]="true"
@@ -27,14 +27,16 @@
</i>
</span>
<!-- Page title -->
<span [innerHtml]="result.labelHtml"></span>
@if (result.package) {
<span
[innerHTML]="result.package"
class="docs-search-result__label__package"
></span>
}
<!-- Page title and package badge -->
<span class="docs-search-result__label__text">
<span [innerHtml]="result.labelHtml"></span>
@if (result.package) {
<span
[innerHTML]="result.package"
class="docs-search-result__label__package"
></span>
}
</span>
</p>
@if (result.subLabelHtml) {
@@ -63,12 +65,22 @@
<docs-search-history />
} @else {
<div class="docs-search-results docs-mini-scroll-track">
@if (!resultsResource.hasValue()) {
@if (emptyState() === 'start') {
<div class="docs-search-results__start-typing">
<img
src="assets/images/angie/magnifying-glass.svg"
class="docs-search-angie"
aria-hidden="true"
/>
<span>Start typing to see results</span>
</div>
} @else if (searchResults().length === 0) {
} @else {
<div class="docs-search-results__no-results">
<img
src="assets/images/angie/question.svg"
class="docs-search-angie"
aria-hidden="true"
/>
<span>No results found</span>
</div>
}
@@ -46,6 +46,7 @@ dialog {
.docs-search-result-icon {
display: inline-block;
flex-shrink: 0;
i {
display: flex;
@@ -91,7 +92,20 @@ dialog {
&__label {
font-weight: 600;
flex-wrap: wrap;
&__text {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 0.25rem 0.5rem;
flex: 1;
min-width: 0;
overflow-wrap: break-word;
> * {
min-width: 0;
}
}
&__package {
font-size: 0.75rem;
@@ -136,15 +150,25 @@ dialog {
.docs-search-results__start-typing,
.docs-search-results__no-results {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.75rem;
color: var(--gray-400);
color: var(--quaternary-contrast);
}
.docs-search-angie {
width: 210px;
height: auto;
aspect-ratio: 1;
margin-block: -1rem -0.5rem;
}
.docs-search-footer {
display: flex;
align-items: center;
justify-content: space-between;
color: var(--gray-400);
color: var(--quaternary-contrast);
padding: 1rem;
font-size: 0.75rem;
font-weight: 500;
@@ -14,7 +14,7 @@ import {Router, provideRouter} from '@angular/router';
import {SearchDialog} from './search-dialog.component';
import {ENVIRONMENT, WINDOW} from '../../providers';
import {ALGOLIA_CLIENT, Search} from '../../services';
import {FakeEventTarget} from '../../testing/index';
import {FakeEventTarget, timeout, useAutoTick} from '../../testing/index';
import {AlgoliaIcon} from '../algolia-icon/algolia-icon.component';
import {SearchResult} from '../../interfaces';
@@ -27,8 +27,10 @@ describe('SearchDialog', () => {
let search: Search;
useAutoTick();
beforeEach(async () => {
searchResults.and.returnValue([]);
searchResults.and.returnValue(Promise.resolve({results: [{hits: []}]}));
TestBed.configureTestingModule({
imports: [SearchDialog],
@@ -55,6 +57,9 @@ describe('SearchDialog', () => {
// Fire the request
TestBed.inject(ApplicationRef).tick();
// The delay from debounced (200ms)
await timeout(300);
// Wait for the resource to resolve
await TestBed.inject(ApplicationRef).whenStable();
@@ -85,6 +90,9 @@ describe('SearchDialog', () => {
// Fire the request
TestBed.inject(ApplicationRef).tick();
// The delay from debounced (200ms)
await timeout(300);
// Wait for the resource to resolve
await TestBed.inject(ApplicationRef).whenStable();
@@ -96,7 +104,7 @@ describe('SearchDialog', () => {
});
it('should display `Start typing to see results` message when there are no provided query', () => {
searchResults.and.returnValue(undefined);
searchResults.and.returnValue(Promise.resolve(undefined));
const startTypingContainer = fixture.debugElement.query(
By.css('.docs-search-results__start-typing'),
@@ -105,6 +113,35 @@ describe('SearchDialog', () => {
expect(startTypingContainer).toBeTruthy();
});
it('should keep the `No results found` message while re-querying instead of flickering back to `Start typing`', async () => {
const appRef = TestBed.inject(ApplicationRef);
// Settle on an empty result set so `No results found` is shown.
search.searchQuery.set('foobarbaz');
searchResults.and.returnValue(Promise.resolve({results: [{hits: []}]}));
appRef.tick();
await timeout(300);
await appRef.whenStable();
expect(fixture.debugElement.query(By.css('.docs-search-results__no-results'))).toBeTruthy();
// Edit the query so a new search goes in flight and stays pending.
let resolveReload!: (value: unknown) => void;
searchResults.and.returnValue(new Promise((resolve) => (resolveReload = resolve)));
search.searchQuery.set('foobarba');
appRef.tick();
// The delay from debounced (200ms), after which the pending request is loading.
await timeout(300);
// While the re-query is loading it must not revert to the `Start typing` state.
expect(fixture.debugElement.query(By.css('.docs-search-results__start-typing'))).toBeNull();
expect(fixture.debugElement.query(By.css('.docs-search-results__no-results'))).toBeTruthy();
resolveReload({results: [{hits: []}]});
await appRef.whenStable();
});
it('should display list of the search results when results exist', async () => {
search.searchQuery.set('fakeQuery');
searchResults.and.returnValue(Promise.resolve({results: [{hits: fakeSearchResults}]}));
@@ -112,6 +149,9 @@ describe('SearchDialog', () => {
// Fire the request
TestBed.inject(ApplicationRef).tick();
// The delay from debounced (200ms)
await timeout(300);
// Wait for the resource to resolve
await TestBed.inject(ApplicationRef).whenStable();
@@ -8,7 +8,6 @@
import {
afterNextRender,
ChangeDetectionStrategy,
Component,
DestroyRef,
effect,
@@ -33,10 +32,10 @@ import {RelativeLink} from '../../pipes';
import {AlgoliaIcon} from '../algolia-icon/algolia-icon.component';
import {SearchHistoryComponent} from '../search-history/search-history.component';
import {TextField} from '../text-field/text-field.component';
import {getRelativeUrl} from '../../utils';
@Component({
selector: 'docs-search-dialog',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
ClickOutside,
TextField,
@@ -57,7 +56,7 @@ export class SearchDialog {
readonly history = inject(SearchHistory);
private readonly search = inject(Search);
private readonly relativeLink = new RelativeLink();
private readonly router = inject(Router);
private readonly window = inject(WINDOW);
private readonly injector = inject(Injector);
@@ -68,6 +67,7 @@ export class SearchDialog {
readonly resultsResource = this.search.resultsResource;
readonly searchResults = this.search.searchResults;
readonly emptyState = this.search.emptyState;
searchForm = form(this.search.searchQuery);
@@ -122,7 +122,7 @@ export class SearchDialog {
return;
}
this.router.navigateByUrl(this.relativeLink.transform(activeItemLink));
this.router.navigateByUrl(getRelativeUrl(activeItemLink));
this.onClose.emit();
}
}
@@ -28,6 +28,7 @@ ng_project(
"//adev/shared-docs/directives",
"//adev/shared-docs/pipes",
"//adev/shared-docs/services",
"//adev/shared-docs/utils",
],
)
@@ -6,9 +6,10 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ActiveDescendantKeyManager} from '@angular/cdk/a11y';
import {NgTemplateOutlet} from '@angular/common';
import {
afterNextRender,
ChangeDetectionStrategy,
Component,
DestroyRef,
effect,
@@ -16,14 +17,13 @@ import {
Injector,
viewChildren,
} from '@angular/core';
import {Router, RouterLink} from '@angular/router';
import {toSignal} from '@angular/core/rxjs-interop';
import {ActiveDescendantKeyManager} from '@angular/cdk/a11y';
import {NgTemplateOutlet} from '@angular/common';
import {Router, RouterLink} from '@angular/router';
import {SearchHistory} from '../../services';
import {RelativeLink} from '../../pipes';
import {SearchItem} from '../../directives';
import {RelativeLink} from '../../pipes';
import {SearchHistory} from '../../services';
import {getRelativeUrl} from '../../utils';
@Component({
selector: 'docs-search-history',
@@ -34,7 +34,6 @@ import {SearchItem} from '../../directives';
'(document:keydown)': 'onKeydown($event)',
'(document:mousemove)': 'onMouseMove($event)',
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SearchHistoryComponent {
protected readonly items = viewChildren(SearchItem);
@@ -43,7 +42,6 @@ export class SearchHistoryComponent {
private readonly injector = inject(Injector);
private readonly router = inject(Router);
private readonly relativeLink = new RelativeLink();
private readonly keyManager = new ActiveDescendantKeyManager(
this.items,
this.injector,
@@ -101,7 +99,7 @@ export class SearchHistoryComponent {
const activeItemLink = this.keyManager.activeItem?.item()?.url;
if (activeItemLink) {
const url = this.relativeLink.transform(activeItemLink);
const url = getRelativeUrl(activeItemLink);
this.router.navigateByUrl(url);
}
}
@@ -16,6 +16,7 @@ ng_project(
],
deps = [
"//adev:node_modules/@angular/aria",
"//adev:node_modules/@angular/cdk",
"//adev:node_modules/@angular/common",
"//adev:node_modules/@angular/core",
"//adev:node_modules/@angular/forms",
@@ -1,61 +1,94 @@
<div ngCombobox #outerCombobox="ngCombobox" [readonly]="true" [disabled]="disabled()">
<div class="docs-select-input-container">
<div ngCombobox #combobox="ngCombobox" class="docs-combobox-container" [(expanded)]="popupExpanded">
<div #origin class="docs-select-input-container">
<input
ngComboboxInput
[attr.id]="id()"
[attr.name]="name()"
[value]="displayValue()"
placeholder="Select an option..."
placeholder="Select an option"
readonly
[tabindex]="-1"
/>
<span class="material-symbols-outlined docs-select-arrow" translate="no" aria-hidden="true"
>arrow_drop_down</span
>
</div>
<ng-template ngComboboxPopupContainer>
<dialog ngComboboxDialog class="docs-select-dialog">
<div ngCombobox #innerCombobox="ngCombobox" filterMode="manual" [alwaysExpanded]="true">
<div class="docs-select-search-container">
<span
class="material-symbols-outlined docs-select-search-icon"
translate="no"
aria-hidden="true"
>search</span
>
<input
ngComboboxInput
class="docs-select-search-input"
placeholder="Search..."
[(value)]="searchString"
/>
</div>
<ng-template ngComboboxPopupContainer>
@if (filteredOptions().length === 0) {
<div class="docs-select-no-results">No results found</div>
}
<div ngListbox [(values)]="selectedValues" class="docs-select-listbox">
@for (option of filteredOptions(); track option.value) {
<div
ngOption
[value]="option.value"
[label]="option.label"
class="docs-select-option"
<ng-template
[cdkConnectedOverlay]="{origin: combobox.element, usePopover: 'inline', matchWidth: true}"
[cdkConnectedOverlayOpen]="popupExpanded()"
[cdkConnectedOverlayDisableClose]="false"
(overlayOutsideClick)="popupExpanded.set(false)"
>
<ng-template ngComboboxPopup [combobox]="combobox" popupType="dialog">
<div class="docs-select-popover">
<div class="docs-select-dialog" ngComboboxWidget>
<div class="example-combobox-container">
<div class="docs-select-search-container">
<span
class="material-symbols-outlined docs-select-search-icon"
translate="no"
aria-hidden="true"
>search</span
>
<span class="docs-select-option-label">{{ option.label }}</span>
<span
class="material-symbols-outlined docs-select-check-icon"
translate="no"
aria-hidden="true"
>check</span
<input
ngCombobox
#innerCombobox="ngCombobox"
#searchInput
class="docs-select-search-input"
placeholder="Search..."
[(value)]="searchString"
[alwaysExpanded]="true"
(keydown.escape)="onSearchEscape($event)"
/>
</div>
<div aria-live="polite" class="cdk-visually-hidden">
{{ filteredOptions().length === 0 ? 'No results found for ' + searchString() : '' }}
</div>
<ng-template ngComboboxPopup [combobox]="innerCombobox">
<div class="example-popup example-popup-no-margin">
@if (filteredOptions().length === 0) {
<div class="docs-select-no-results">
<img
src="assets/images/angie/question.svg"
class="docs-select-no-results-angie"
aria-hidden="true"
/>
<span>No results found</span>
</div>
}
<div
#listbox="ngListbox"
ngListbox
[(value)]="selectedValues"
[multi]="false"
ngComboboxWidget
class="docs-select-listbox"
focusMode="activedescendant"
tabindex="-1"
selectionMode="explicit"
(click)="onCommit()"
(keydown.enter)="onCommit()"
[activeDescendant]="listbox.activeDescendant()"
[class.example-empty]="filteredOptions().length === 0"
>
@for (option of filteredOptions(); track option.value) {
<div
ngOption
[value]="option.value"
[label]="option.label"
class="docs-select-option"
>
<span class="docs-select-option-label">{{ option.label }}</span>
</div>
}
</div>
</div>
}
</ng-template>
</div>
</ng-template>
</div>
</div>
</dialog>
</ng-template>
</ng-template>
</div>
@@ -1,14 +1,16 @@
:host {
--border-color: color-mix(in srgb, var(--full-contrast) 20%, var(--page-background));
}
[ngCombobox] {
position: relative;
width: 100%;
display: flex;
flex-direction: column;
}
.docs-combobox-container {
border: 1px solid var(--border-color);
border-radius: 0.25rem;
overflow: hidden;
}
.docs-select-input-container {
@@ -16,15 +18,25 @@
position: relative;
align-items: center;
border-radius: 0.25rem;
}
[ngComboboxInput] {
border-radius: 0.25rem;
}
input {
width: 100%;
border: none;
outline: none;
font-size: 1rem;
padding: 0.7rem 1rem 0.7rem;
background-color: var(--septenary-contrast);
color: var(--primary-contrast);
[ngComboboxInput][readonly='true'] {
cursor: pointer;
padding: 0.7rem 1rem;
&[readonly] {
cursor: pointer;
padding: 0.7rem 1rem;
}
&[aria-expanded='true'] + .docs-select-arrow {
transform: rotate(180deg);
}
}
}
[ngCombobox]:focus-within [ngComboboxInput]:not(.docs-select-search-input) {
@@ -32,6 +44,10 @@
box-shadow: 0 0 0 4px color-mix(in srgb, var(--vivid-pink) 25%, transparent);
}
.docs-select-popover {
width: 100%;
}
.docs-select-arrow {
width: 24px;
height: 24px;
@@ -46,22 +62,19 @@
transition: transform 0.2s ease;
}
[ngComboboxInput][aria-expanded='true'] + .docs-select-arrow {
transform: rotate(180deg);
}
[ngComboboxInput] {
width: 100%;
[ngComboboxInput] [ngCombobox] {
border: none;
outline: none;
font-size: 1rem;
padding: 0.7rem 1rem 0.7rem 2.5rem;
padding: 0.7rem 1rem 0.7rem;
background-color: var(--septenary-contrast);
color: var(--primary-contrast);
}
.docs-select-dialog {
position: absolute;
box-sizing: border-box;
width: 100%;
left: auto;
right: auto;
top: auto;
@@ -69,6 +82,7 @@
padding: 0;
border: 1px solid var(--border-color);
border-radius: 0.25rem;
overflow: hidden;
background-color: var(--septenary-contrast);
color: inherit;
@@ -135,6 +149,10 @@
}
.docs-select-no-results {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
padding: 0.75rem;
text-align: center;
font-size: 0.875rem;
@@ -142,11 +160,18 @@
opacity: 0.7;
}
.docs-select-no-results-angie {
width: 88px;
height: auto;
aspect-ratio: 1;
}
.docs-select-listbox {
display: flex;
flex-direction: column;
max-height: 12rem;
overflow: auto;
overscroll-behavior: contain;
padding: 0.25rem;
}
@@ -171,16 +196,8 @@
color: var(--vivid-pink);
background-color: color-mix(in srgb, var(--vivid-pink) 5%, transparent);
}
&:not([aria-selected='true']) .docs-select-check-icon {
display: none;
}
}
.docs-select-option-label {
flex: 1;
}
.docs-select-check-icon {
font-size: 0.9rem;
}
@@ -1,4 +1,4 @@
/*!
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
@@ -6,28 +6,21 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {
Combobox,
ComboboxDialog,
ComboboxInput,
ComboboxPopupContainer,
} from '@angular/aria/combobox';
import {Combobox, ComboboxPopup, ComboboxWidget} from '@angular/aria/combobox';
import {Listbox, Option} from '@angular/aria/listbox';
import {OverlayModule} from '@angular/cdk/overlay';
import {
afterRenderEffect,
ChangeDetectionStrategy,
Component,
computed,
input,
model,
signal,
untracked,
viewChild,
} from '@angular/core';
import {FormValueControl} from '@angular/forms/signals';
import {FormsModule} from '@angular/forms';
type SelectOptionValue = string | number | boolean;
type SelectOptionValue = string;
export interface SelectOption {
label: string;
@@ -36,18 +29,9 @@ export interface SelectOption {
@Component({
selector: 'docs-select',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
Combobox,
ComboboxDialog,
ComboboxInput,
ComboboxPopupContainer,
FormsModule,
Listbox,
Option,
],
templateUrl: './select.component.html',
styleUrls: ['./select.component.scss'],
templateUrl: 'select.component.html',
styleUrl: 'select.component.css',
imports: [Combobox, ComboboxPopup, ComboboxWidget, Listbox, Option, OverlayModule],
})
export class Select implements FormValueControl<string | null> {
readonly value = model<string | null>(null);
@@ -55,14 +39,13 @@ export class Select implements FormValueControl<string | null> {
readonly id = input.required<string>({alias: 'selectId'});
readonly name = input.required<string>();
readonly options = input.required<SelectOption[]>();
readonly disabled = input(false);
readonly dialog = viewChild(ComboboxDialog);
readonly listbox = viewChild<Listbox<SelectOptionValue>>(Listbox);
readonly combobox = viewChild<Combobox<SelectOptionValue>>(Combobox);
readonly listbox = viewChild(Listbox);
readonly combobox = viewChild(Combobox);
readonly searchString = signal('');
readonly popupExpanded = signal(false);
readonly filteredOptions = computed(() => {
const search = this.searchString().toLowerCase();
if (!search) {
@@ -84,39 +67,36 @@ export class Select implements FormValueControl<string | null> {
constructor() {
afterRenderEffect(() => {
if (this.dialog() && this.combobox()?.expanded()) {
untracked(() => this.listbox()?.gotoFirst());
this.positionDialog();
}
this.listbox()?.scrollActiveItemIntoView();
});
afterRenderEffect(() => {
const selected = this.selectedValues();
if (selected.length > 0) {
untracked(() => this.dialog()?.close());
this.value.set(selected[0] as string);
this.searchString.set('');
}
});
afterRenderEffect(() => this.listbox()?.scrollActiveItemIntoView());
}
// TODO: Improve once CDK overlay is fixed https://github.com/angular/components/issues/32504
private positionDialog(): void {
const dialog = this.dialog();
const combobox = this.combobox();
if (!dialog || !combobox) {
return;
onCommit() {
const values = this.selectedValues();
if (values.length) {
this.value.set(values[0]);
this.popupExpanded.set(false);
}
}
const comboboxRect = combobox.inputElement()?.getBoundingClientRect();
const scrollY = window.scrollY;
/** Dismisses the dialog overlay on Escape key. */
onSearchEscape(event: Event) {
this.popupExpanded.set(false);
this.combobox()?.element.focus();
}
if (comboboxRect) {
dialog.element.style.width = `${comboboxRect.width}px`;
dialog.element.style.top = `${comboboxRect.bottom + scrollY + 4}px`;
dialog.element.style.left = `${comboboxRect.left}px`;
/** Handles keydown events on the clear button. */
onKeydown(event: KeyboardEvent): void {
if (event.key === 'Enter') {
this.clear();
this.popupExpanded.set(false);
event.stopPropagation();
}
}
/** Clears the search query and all selected options. */
clear(): void {
this.searchString.set('');
this.value.set(null);
}
}
@@ -6,12 +6,11 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ChangeDetectionStrategy, Component, input, model} from '@angular/core';
import {Component, input, model} from '@angular/core';
import {FormCheckboxControl} from '@angular/forms/signals';
@Component({
selector: 'docs-slide-toggle',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './slide-toggle.component.html',
styleUrls: ['./slide-toggle.component.scss'],
})
@@ -8,7 +8,6 @@
import {
afterRenderEffect,
ChangeDetectionStrategy,
Component,
computed,
ElementRef,
@@ -33,7 +32,6 @@ let idCounter = 0;
host: {
class: 'docs-tab-group',
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TabGroup {
private readonly _renderer = inject(Renderer2);
@@ -6,23 +6,14 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {
ChangeDetectionStrategy,
Component,
DestroyRef,
input,
inject,
afterNextRender,
signal,
} from '@angular/core';
import {Location, ViewportScroller} from '@angular/common';
import {afterNextRender, Component, DestroyRef, inject, input, signal} from '@angular/core';
import {TableOfContentsLevel} from '../../interfaces/index';
import {TableOfContentsLoader} from '../../services';
import {IconComponent} from '../icon/icon.component';
@Component({
selector: 'docs-table-of-contents',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './table-of-contents.component.html',
styleUrls: ['./table-of-contents.component.scss'],
imports: [IconComponent],
@@ -6,21 +6,12 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {
afterNextRender,
ChangeDetectionStrategy,
Component,
ElementRef,
input,
model,
viewChild,
} from '@angular/core';
import {afterNextRender, Component, ElementRef, input, model, viewChild} from '@angular/core';
import {FormValueControl} from '@angular/forms/signals';
import {IconComponent} from '../icon/icon.component';
@Component({
selector: 'docs-text-field',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [IconComponent],
templateUrl: './text-field.component.html',
styleUrls: ['./text-field.component.scss'],
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {ChangeDetectionStrategy, Component, inject, input, linkedSignal} from '@angular/core';
import {Component, inject, input, linkedSignal} from '@angular/core';
import {ExternalLink} from '../../directives';
import {LOCAL_STORAGE} from '../../providers';
import {IconComponent} from '../icon/icon.component';
@@ -18,7 +18,6 @@ export const STORAGE_KEY_PREFIX = 'docs-was-closed-top-banner-';
imports: [ExternalLink, IconComponent],
templateUrl: './top-level-banner.component.html',
styleUrl: './top-level-banner.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TopLevelBannerComponent {
private readonly localStorage = inject(LOCAL_STORAGE);
@@ -71,6 +71,7 @@ ts_project(
"//adev/shared-docs/interfaces",
"//adev/shared-docs/providers",
"//adev/shared-docs/services",
"//adev/shared-docs/utils",
],
)
@@ -132,6 +132,7 @@
.docs-page-title {
display: flex;
justify-content: space-between;
align-items: baseline;
h1 {
margin-block: 0;
@@ -143,7 +144,7 @@
height: fit-content;
docs-icon {
color: var(--gray-400);
color: var(--quaternary-contrast);
transition: color 0.3s ease;
}

Some files were not shown because too many files have changed in this diff Show More