Commit graph

332 commits

Author SHA1 Message Date
arturovt
119a19e604 fix(platform-server): forward BEFORE_APP_SERIALIZED errors to ErrorHandler
Some checks failed
DevInfra / assistant_to_the_branch_manager (push) Has been cancelled
CI (push) / lint (push) Has been cancelled
CI (push) / devtools (push) Has been cancelled
CI (push) / test (push) Has been cancelled
CI (push) / integration-tests (push) Has been cancelled
CI (push) / adev (push) Has been cancelled
CI (push) / vscode-ng-language-service (push) Has been cancelled
CI (push) / publish-snapshots (push) Has been cancelled
CI (push) / zone-js (push) Has been cancelled
Update ADEV Cross Repo Docs / Update Cross Repo ADEV Docs (push) Has been cancelled
CI (push) / adev-deploy (push) Has been cancelled
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

(cherry picked from commit 7623580378)
2026-05-08 14:10:16 -07:00
Alan Agius
a451a1d66e 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

(cherry picked from commit 60552a73e8)
2026-05-07 15:30: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
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
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
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
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
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
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
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
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
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
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
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
Kristiyan Kostadinov
81cabc1477 feat(core): add support for TypeScript 6
Updates the project to support TypeScript 6 and accounts for some of the breakages.
2026-02-17 08:40:38 -08:00
Matthieu Riegler
08ea105aa3 refactor(platform-server): split zone/zoneless tests.
The Zone tests are a subset of tests that we still using the Zone CD provider.
2026-02-13 09:41:10 -08:00
Angular Robot
11767cabe4 build: update Jasmine to 6.0.0
Jasmine enables `forbidDuplicateNames: true` by default. So we also need to desambiguate duplicate spec names.
2026-02-09 12:15:57 -08:00
Jessica Janiuk
30e9c62bdf fix(core): fix memory leak with event replay
This ensures event replay does not hold on to elements after an application has been destroyed.

fixes: #59261
2026-01-07 14:27:44 -08:00
Matthieu Riegler
6270bba056 ci: reformat files
This is after we've slightly changed a rule in #66056
2025-12-16 14:44:19 -08:00
Alan Agius
400fc82c43 refactor: replace getDocument() with inject(DOCUMENT)
This replaces `getDocument()` with `inject(DOCUMENT)` across hydration and transfer state logic.
2025-11-25 13:04:58 -05:00
Doug Parker
ec9dc94cee feat(platform-browser): add context to createApplication
This is necessary to use SSR safely with `createApplication` and avoid constraining users to `bootstrapApplication`. It is one more step towards feature parity between `createApplication` and `bootstrapApplication`.
2025-11-10 14:18:29 -08:00
Alan Agius
062a696673 refactor(platform-server): use URL constructor for robust parsing (#64494)
The existing implementation of `PlatformLocation` uses a custom URL parsing mechanism that can be brittle and doesn't properly update the `href` property. This change refactors the URL parsing to use the native `URL` constructor, providing more robust and accurate parsing of URLs, which also correctly updates the `href` property.

The tests for `PlatformLocation` have also been moved to a dedicated file to improve organization and clarity.

PR Close #64494
2025-10-17 18:17:15 +00:00
Matthieu Riegler
dd2f53b9cd refactor(core): warning when hydration trigger is used without hydration being enabled (#64185)
This replaces the error we were throwing before the change. This allows component with defer triggerrs to be used on both SSR'd and CSR.

fixes #64184

PR Close #64185
2025-10-14 11:55:21 -07:00
Kristiyan Kostadinov
ad2376435b feat(core): support IntersectionObserver options in viewport triggers (#64130)
Adds support for customizing the `IntersectionObserver` options for the `on viewport`, `prefetch on viewport` and `hydrate on viewport` triggers.

Note that the options need to be a static object literal, e.g. `@defer (on viewport(trigger, {rootMargin: '123px'})`.

Fixes #52799.

PR Close #64130
2025-10-09 05:32:21 -07:00
Kristiyan Kostadinov
f5b50ec20d refactor: clean up explicit standalone flags from tests (#63963)
Since standalone is the default, we can dropn the `standalone: true` flags from our tests.

PR Close #63963
2025-09-22 14:27:34 +00:00
Leon Senft
f008045ded fix(core): do not rename ARIA property bindings to attributes (#63925)
https://github.com/angular/angular/pull/62630 made it so that all ARIA
property bindings would write to their corresponding attribute instead.
The primary motivation for this change was to ensure that ARIA
attributes were always rendered correctly on the server, where the
emulated DOM may not correctly reflect ARIA properties as attributes.
Furthermore, this change added support for binding to ARIA attributes
using the property binding syntax (e.g. `[aria-label]`).

Unfortunately, https://github.com/angular/angular/pull/62630 relied on
the incorrect assumptions that an ARIA property name could be converted
to its attribute name (without hardcoding the conversion), and that the
value of an ARIA property matched its corresponding attribute. For
example, the `ariaLabelledByElements` property's value is an array of
DOM elements, while the corresponding `aria-labelledby` attribute's
value is a string containing the IDs of the DOM elements.

This partially reverts https://github.com/angular/angular/pull/62630 so
that only property bindings with ARIA attribute names (begin with
`aria-`) are converted to attribute bindings.

* `[ariaLabel]` will revert to binding to the `ariaLabel` property.
* `[aria-label]` will continue binding to the `aria-label` attribute.

Note the only difference between `[aria-label]` and `[attr.aria-label]`
is that the former will attempt to bind to inputs of the same name while
the latter will not.

PR Close #63925
2025-09-19 14:50:39 +00:00
Andrew Scott
0d028e0f77 refactor(platform-browser): Remove zonejs compatibility detector (#63847)
The zoneless scheduler is always enabled, so if hydration works with zoneless, it works
for all Angular apps. There is no need for detection of custom zone implementations

PR Close #63847
2025-09-16 22:16:49 +00:00
SkyZeroZx
d2163f3701 test(platform-server): add test for transfer state data in nested defer blocks (#63801)
Add test for transfer state data in nested defer blocks

PR Close #63801
2025-09-15 15:34:59 +00:00
Jessica Janiuk
4924108630 refactor(core): dispatch enter and leave animations at the right times (#63450)
This updates the enter and leave logic to use the stored LView data to dispatch the enter and leave animations at the right points in the lifecycle. This should fix issues with signals not being available yet, parallel animations, and also eliminate the need for the element registry.

fixes: #63391
fixes: #63388
fixes: #63369

PR Close #63450
2025-09-10 22:24:00 +00:00
Andrew Scott
c3576506b3 refactor(core): Update tests for zoneless by default (#63668)
This updates tests and examples only to prepare for zoneless by default.

These changes were identified and made as part of #63382. Anything that
failed gets `provideZoneChangeDetection` unless the fixes were easily
and quickly determined.

It also adds the zoneless provider to the `initTestEnvironment` calls
for tests in this repo to prevent regressions before #63382 is merged.

PR Close #63668
2025-09-09 14:41:56 -07:00
Alan Agius
28926ba92c feat(core): introduce BootstrapContext for improved server bootstrapping (#63562)
This commit introduces a number of changes to the server bootstrapping process to make it more robust and less error-prone, especially for concurrent requests.

Previously, the server rendering process relied on a module-level global platform injector. This could lead to issues in server-side rendering environments where multiple requests are processed concurrently, as they could inadvertently share or overwrite the global injector state.

The new approach introduces a `BootstrapContext` that is passed to the `bootstrapApplication` function. This context provides a platform reference that is scoped to the individual request, ensuring that each server-side render has an isolated platform injector. This prevents state leakage between concurrent requests and makes the overall process more reliable.

BREAKING CHANGE:
The server-side bootstrapping process has been changed to eliminate the reliance on a global platform injector.

Before:
```ts
const bootstrap = () => bootstrapApplication(AppComponent, config);
```

After:
```ts
const bootstrap = (context: BootstrapContext) =>
  bootstrapApplication(AppComponent, config, context);
```

A schematic is provided to automatically update `main.server.ts` files to pass the `BootstrapContext` to the `bootstrapApplication` call.

In addition, `getPlatform()` and `destroyPlatform()` will now return `null` and be a no-op respectively when running in a server environment.

PR Close #63562
2025-09-09 10:57:09 -07:00
Andrew Scott
5b53535dd1 fix(router): Update recognize stage to use internally async/await (#62994)
This is effectively a revert of 72e6a948bb.
Debugging the recognize stage is considerably easier with async/await
stacks compared to rxjs. This also improves maintainability and is a
better 1:1 with server-side logic that has been implemented to match
and can be more easily kept in sync.

This also ensures that the recognize step is always async, whereas it
can sometimes be synchronous with rxjs.

BREAKING CHANGE: Router navigations may take several additional
microtasks to complete. Tests have been found to often be highly
dependent on the exact timing of navigation completions with respect to
the microtask queue. The most common fix for tests is to ensure all
navigations have been completed before making assertions. On rare
occasions, this can also affect production applications. This can be
caused by multiple subscriptions to router state throughout the application,
both of which trigger navigations that happened to not conflict with the
previous timing.

PR Close #62994
2025-08-29 08:55:13 -07:00
Hongxu Xu
1f4c5f72aa refactor(bazel): reduce build deps (#63348)
clean up deps in bazel build scripts

PR Close #63348
2025-08-28 09:16:10 -07:00
Joey Perrott
2fcafb65c5 build: rename defaults2.bzl to defaults.bzl (#63383)
Use defaults.bzl for the common macros

PR Close #63383
2025-08-25 15:45:01 -07:00
Joey Perrott
3df1dccebe refactor: various build and import specificer fixes for strict deps (#63323)
Change direct deps in bazel targets and import specifiers within files to maintain strict deps requirements ahead of enabling strict deps tests in the repo

PR Close #63323
2025-08-22 14:45:00 -07:00
Joey Perrott
cbc258eec8 build: remove ts_project_interop infrastructure (#62908)
Remove the interop macros and final usages

PR Close #62908
2025-07-31 09:12:58 +00:00
Leon Senft
4138aca91f feat(core): render ARIA property bindings as attributes (#62630)
Allow binding to ARIA attributes using property binding syntax _without_
the `attr.` prefix. For example, `[aria-label]="expr"` is now valid, and
equivalent to `[ariaLabel]="expr"`. Both examples bind to either a
matching input or the `aria-label` HTML attribute, rather than the
`ariaLabel` DOM property.

Binding ARIA properties as attributes will ensure they are rendered
correctly on the server, where the emulated DOM may not correctly
reflect ARIA properties as attributes.

Reuse the DOM schema registry from the compiler to map property names in
type check blocks.

PR Close #62630
2025-07-22 06:59:00 -04:00
Matthieu Riegler
db3c928305 refactor(core): add a getTransferState for the devtools (#62722)
`getTransferState` will expose public data from the transfer state. It will for example remove internal hydration data.

PR Close #62722
2025-07-21 17:00:27 -04:00
Joey Perrott
8bf97d1370 build: remove all usages of the interop_deps attr for ts_project and ng_project (#62732)
Remove all of the usages of interop_deps as attributes in the repo

PR Close #62732
2025-07-21 13:03:09 -04:00
Andrew Scott
859958dbfe fix(core): Ensure application remains unstable during bootstrap (#62631)
This commit ensures the application remains unstable during the entire
bootstrap process. This ensures all bootstrap listeners and app
initializers observe the application as being unstable until each one
has gotten a chance to execute the synchronous block (potentially adding
more pending tasks).

Prior to this commit, application initializers or bootstrap
listeners may observe the application as being stable, even though other
initializers/listeners had not yet executed. This created an ordering
issue whereby the hydration bootstrap listener would observe the
application as stable prior to the router performing its initial
navigation.

fixes #62592

PR Close #62631
2025-07-15 07:52:36 -07:00
Joey Perrott
3a0cfd544d build: migrate to using new jasmine_test (#62086)
Use the new jasmine_test based on rules_js instead of jasmine_node_test from rules_nodejs

PR Close #62086
2025-06-18 08:27:26 +02:00
arturovt
31da435854 fix(core): inject APP_ID before injector is destroyed (#61885)
In this commit, we request `APP_ID` outside the `onDestroy` callback because the injector might already be in a destroyed state when the callback runs.

PR Close #61885
2025-06-12 15:56:51 +02:00
Jessica Janiuk
8424b3bcd5 fix(core): Fixes template outlet hydration (#61989)
Projected nodes were missing ssrId information and were skipping annotating template information, which caused templates to be destroyed and recreated rather than hydrated.

fixes: #50543

PR Close #61989
2025-06-12 12:53:21 +02:00
Andrew Kushnir
5fce27d63f fix(core): produce an error when incremental hydration is expected, but not configured (#61741)
This commit updates runtime logic to produce an error when there are some `@defer` blocks with `hydrate` triggers, but the incremental hydration is not enabled via `withIncrementalHydration()`. Previously the check was only detecting the case when `withIncrementalHydration()` is present on the server, but missing on the client. With the change in this commit, the check would be performed on the server as well.

PR Close #61741
2025-05-30 11:14:22 -04:00
Joey Perrott
687e01865f build: migrate platform-server to rules_js (#61589)
Migrate platform-server to use ts_project and ng_project.

PR Close #61589
2025-05-22 11:35:55 -07:00
Paul Gschwendtner
810b0a7e5c refactor: add explicit types for exports relying on inferred call return type (#61312)
As part of the Bazel toolchain migration we noticed that implicit types
generated by the TypeScript compiler sometimes end up referencing types
from other packages (i.e. cross-package imports).

These imports currently work just because the Bazel `ts_library` and
`ng_module` rules automatically inserted a `<amd-module
name="@angular/x" />` into `.d.ts` of packages. This helped TS figure
out how to import a given file. Notably this is custom logic that is not
occuring in vanilla TS or Angular compilations—so we will drop this
magic as part of the toolchain cleanup!

To improve code quality and keep the existing behavior working, we are
doing the following:

- adding a lint rule that reduces the risk of such imports breaking. The
  failure scenario without the rule is that API goldens show unexpected
  diffs, and types might be duplicated in a different package!

- keeping the `<amd-module` headers, but we manually insert them into
  the package entry-points. This should ensure we don't regress
  anywhere; while we also improved general safety around this above.

Long-term, isolated declarations or a lint rule from eslint-typescript
can make this even more robust.

PR Close #61312
2025-05-13 22:45:18 +00:00
Paul Gschwendtner
032b802f54 build: remove irrelevant madge circular deps tests (#61156)
We don't need this tooling anymore because we are already validating
that there are no circular dependencies via the `ng-dev` tooling that
checks `.ts` files directly.

Also these tests never actually failed to my knowledge.

PR Close #61156
2025-05-07 11:28:59 -07:00
Jan Martin
06d6da345f fix(platform-server): less aggressive ngServerMode cleanup (#61106)
Other code may depend on `ngServerMode` and it might have been set
globally / via a bundler. Forcing it to `undefined` in those situations
can lead to hard debug issues where the only symptom is that "suddenly"
browser-specific code paths run on the server and (obviously) break.

PR Close #61106
2025-05-06 09:08:47 -07:00
Andrew Scott
e7f5aa2b52 refactor(core): Remove use of private export PendingTasksInternal where possible (#61049)
This commit removes the use of the privately exported
PendingTasksInternal everywhere except for Router. A follow-up change
will be done to remove that one as well and delete the private export.

PR Close #61049
2025-05-05 08:56:20 -07:00