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.
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
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.
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
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);
});
```
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.
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.
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.
- 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
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
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.
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
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.
Enhances the Chrome DevTools performance profiling integration by adding links to relevant Angular documentation for lifecycle hooks and profiler events.
The `ComponentFactory` has been removed from the public API in #68055.
This commit continues the cleanup and also removes `ModuleWithComponentFactories` from the public API.
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.
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.
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
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.
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.
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.
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.
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.
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