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.
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.
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.
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.
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
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.
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
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.
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
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.
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.
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.
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.
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.
- 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.
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.
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.
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.
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.
- 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
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.
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.
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`.
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.
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.