15737 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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