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
(cherry picked from commit bc3a6cda5d)
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.
(cherry picked from commit d0a748cc1b)
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.
(cherry picked from commit 8afd85c6d7)
The `@property` atrule allows users to define custom CSS variables. These changes update the compiler to account for when namespacing variables.
(cherry picked from commit 9b80d4ce9e)
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.
(cherry picked from commit 1bc7e3c2c3)
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.
(cherry picked from commit 49a797f510)
OnPush is now the default change detection strategy, and tests run zoneless by default, so the explicit configuration is no longer needed.
(cherry picked from commit c235ecef8a)
`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.
(cherry picked from commit 0bdbbcf4a8)
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
(cherry picked from commit f0a271c7bd)
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
(cherry picked from commit 8227e5cf6d)
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
(cherry picked from commit 70756b506c)
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.
(cherry picked from commit caeab598c9)
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
(cherry picked from commit 58d536bc83)
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
(cherry picked from commit 7168bed663)
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.
(cherry picked from commit af26a8c521)
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.
(cherry picked from commit cd771174b9)
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
(cherry picked from commit faafd18a4c)
Replaces the temporary `promiseWithResolvers` polyfill with the
native `Promise.withResolvers()` API in test files and Updates the TypeScript configuration to include the `es2024.promise`.
(cherry picked from commit b5ce15c659)
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.
(cherry picked from commit 8975b4346d)
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
(cherry picked from commit f72600eadd)
`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>
(cherry picked from commit 4c4a705ce3)
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.
(cherry picked from commit 0904f90b13)
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
(cherry picked from commit b3bb36ad87)
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.
(cherry picked from commit 38861ac41b)
bluebirdjs.com no longer resolves. npm lists the GitHub repo as the package's
homepage, so the link now goes there.
(cherry picked from commit 731c838dbb)
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.
(cherry picked from commit 2a4903fec1)
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.
(cherry picked from commit 34817da735)
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.
(cherry picked from commit 66d505e287)
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`.
(cherry picked from commit 915a03ae85)
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.
(cherry picked from commit a46292af26)
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.
(cherry picked from commit 83f7695b2e)
Avoid trimming urlStr with String.prototype.trim() in resolveUrl to ensure URL parsing and resolution align with the WHATWG URL standard.
(cherry picked from commit 3e924cc8db)
Non-finite values all used NumberSymbol.Infinity, so formatNumber(NaN)
rendered as infinity. Locale data already defines NumberSymbol.NaN.
(cherry picked from commit 7596548e9b)
This fix ensures that metadata is properly retained when processing
strict standalone component errors for improved error diagnostics.
(cherry picked from commit 74b294cd51)
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
(cherry picked from commit 168a324cce)
Infer URL parameter values as strings and type preloading work as Observable<void> to match the values produced by these internal flows.
(cherry picked from commit f275d289a0)
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.
(cherry picked from commit 0d7ae16350)
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
(cherry picked from commit e9ba39d671)
`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.
(cherry picked from commit c18261f3fd)