```
Title: TableView selected-cell cursor inversion should be optional via TableStyle

Description:
Currently, when a row/cell is selected in TableView, the first character
of the selected cell is always drawn with inverted colors. This serves as
a visual cursor indicator, but it is not always desired – especially when
the terminal driver already provides its own cursor or the user wants a
cleaner look without the inversion artifact.

We need a flag on `TableStyle` that controls this behavior, so it can be
turned off by default and enabled explicitly when needed.

Acceptance criteria:
- A new `bool` property is added to `TableStyle`, for example
  `InvertSelectedCellFirstCharacter`, defaulting to `false`.
- When this property is `false`, the selected cell is rendered using its
  normal colour scheme with **no** character inversion.
- When the property is `true`, the original behaviour is preserved: the
  first character of the selected cell is inverted.
- The property works in all selection modes: single cell, multi-cell, and
  full-row select.
- Changing the property at runtime and calling `SetNeedsDisplay()` (or
  equivalent) updates the display immediately.
- The `TableEditor` demo scenario in UICatalog should expose a menu
  toggle for this new style flag so that the behaviour can be
  interactively tested.
```

Made selected cell invert first character optional as a TableStyle


## Bug Report: Scroll slider thumb stops tracking when mouse is dragged outside scroll bar bounds

**Observed behavior**
When you click and drag the thumb of a `Scroll` view (or the slider inside a `ScrollBar`) and move the mouse pointer outside the scroll bar’s visible area (e.g., above the top edge or below the bottom edge of a vertical bar, or left/right of a horizontal bar), the thumb stops moving and stays at the last position where the mouse was still inside the bar. Releasing the mouse button at that point leaves the scroll position unchanged, even though the thumb should have been “pushed” to the nearest extreme.

**Expected behavior**
The thumb should continue to follow the mouse movement while the button is held, clamping its position to the valid range (0 to `barSize - thumbSize`). Dragging the mouse far beyond the top of a vertical bar should cause the thumb to move all the way to the top and thus scroll the content to the beginning. The same should happen at the bottom, and analogously for horizontal scrolling. When the user releases the button while the mouse is outside, the scroll position should be committed to the clamped value.

**Steps to reproduce**
1. Create a vertically scrollable `Scroll` or `ScrollBar` with a visible slider thumb.
2. Click and hold the thumb.
3. Slowly drag the mouse upward; the thumb moves.
4. Continue moving the mouse upward well beyond the top boundary of the scroll bar.
5. Observe that the thumb stops mid‑track and does not reach the topmost position.
6. Release the mouse button outside the bar; the scroll position does not reflect the extreme.

**Impact**
This makes it difficult to quickly scroll to the start or end of content using the slider, as the user must carefully stop the mouse inside the bar. It also breaks the expected “draggable to limit” behavior common in GUI scrollbars, causing a confusing and sluggish user experience.

Fix scroll slider when moving mouse outside the host.


**Title:** ANSI response parser incorrectly dispatches late responses after `StopExpecting`

**Background**
The `AnsiResponseParser` (and its base `AnsiResponseParserBase`) supports registering expected response terminators via `ExpectResponse` and cancelling them via `StopExpecting`. When a response matching a cancelled terminator arrives later (a “late” response) the parser must not treat it as a normal expected response.

**Current behavior (bug)**
If you call `StopExpecting` for a particular terminator and then later receive an ANSI sequence that matches that terminator, the parser still invokes the callback originally associated with that terminator. This can corrupt the state of other pending requests and surprise callers who assumed the expectation was fully removed.

**Expected behavior**
- A late response should be silently consumed (i.e. the parser must not release the response as output and must not invoke the callback that was registered with the original `ExpectResponse` call).
- After silently consuming the late response the parser should return to its normal state so that subsequent input (including new `ExpectResponse` registrations and any further response-like sequences) is handled correctly.
- If a new `ExpectResponse` is registered with the same terminator **after** the old one was cancelled, then:
  - The next sequence matching that terminator must be dispatched to the **new** callback.
  - If a delayed response from the original request arrives **after** the new request has already been satisfied, that delayed response should still be swallowed and must not affect the new callback or leak as output.
- The parser must never “leak” ANSI content that was part of a late response back as normal output.

**Technical constraints**
This is about the interplay between the two internal lists that track expected and cancelled-but-still-possible responses. Today the same callback-dispatching logic is used for both, which causes the bug. The fix should ensure that matching a late response results only in state cleanup (remove from the late list, reset accumulated state) without invoking the callback, while matching an actively expected response continues to invoke the callback. No public API change is required.

**Acceptance criteria**
- A test that:
  - Registers an expectation, cancels it, registers a new expectation with the same terminator.
  - Feeds a sequence that matches the new expectation → the new callback fires with the correct full response content.
  - Feeds a second matching sequence (the late response) → it is consumed silently; the original callback never fires, and the new callback is not invoked again.
  - After consuming the late response, a third matching sequence is passed, and it leaks through to output (no expectation remains).


```
Fix TabView drawing overflow: clip content redraw to bounds

TabView.Redraw does not clip the content view's drawing to its bounds,
so long content can overflow and corrupt the display. Ensure the
content view is drawn with a clip that matches its own bounds, and
restore the previous clip afterwards so other drawing is not affected.
```

Fixes #1846. TabView now clip the draw bounds (#1847)


### Bug Report: CharMap Crashes on Zero-Width ModifierSymbol Runes (e.g., Emoji Skin Tone Modifiers)

**Summary**
The `CharMap` control throws an `InvalidOperationException` whenever it attempts to render a Unicode codepoint that belongs to the `UnicodeCategory.ModifierSymbol` class and has zero display width. This affects, for example, the emoji skin tone modifiers U+1F3FB through U+1F3FF. The crash makes it impossible to browse the affected regions of the Unicode character map.

**Steps to Reproduce**
1. Instantiate a `CharMap` view.
2. Set `StartCodePoint` (or navigate) to a code block that contains a zero‑width `ModifierSymbol` codepoint (e.g., U+1F3FB).
3. Let the control attempt to draw the grid of characters – an `InvalidOperationException` is thrown.

**Expected Behavior**
- The control should render the zero‑width codepoint without crashing.
  - Since the codepoint itself has no visible width, a reasonable placeholder could be shown (e.g., a highlighted letter or symbol indicating the category, similar to how other zero‑width non‑printing characters are handled).
- If any zero‑width rune is encountered whose `UnicodeCategory` is not explicitly handled, the control should fall back to displaying a clear placeholder (like “?”) instead of throwing an exception, so that future Unicode additions do not cause crashes.

**Actual Behavior**
A fatal `InvalidOperationException` is thrown with a message similar to:
`"The Rune … has zero width and no special-case UnicodeCategory logic applies."`

**Impact**
- Browsing the Unicode map near the emoji modifier block is impossible.
- Users lose the ability to inspect codepoints that are valid Unicode characters and are essential for correct emoji composition in modern applications.
- The lack of a generic fallback means any future zero‑width category not yet coded will also crash the control.

**Additional Context**
The `ModifierSymbol` runes are designed to combine with a preceding base character (hence their zero advance width), but they are still valid codepoints that users will encounter when exploring the full Unicode repertoire. The map should treat them gracefully, just as it already does for other non‑printing categories (like `Format` or `OtherNotAssigned`).

Fixes #4817. CharMap: handle zero-width ModifierSymbol runes without throwing (#4818)


**Request: Output drivers must guard against terminal I/O when not attached to a real terminal**

When the process is not connected to a real terminal (e.g. stdout is redirected, running in a CI environment, or the console is a pseudo-terminal that doesn’t support full screen operations), all output driver operations should become safe no-ops or return sensible defaults without emitting escape sequences, text, or making system calls that assume a real console.

**Acceptance criteria**

1. **No output written** – For `AnsiOutput`, `NetOutput`, `UnixOutput`, and `WindowsOutput`, calls to `Write`, `Write (IOutputBuffer)`, `SetCursor`, `Suspend`, `Dispose`, and any internal `SetCursorPositionImpl` should immediately return without writing to the underlying stream or handle when `IsAttachedToTerminal` is `false`.

2. **Cursor state tracking** – `SetCursor` may still update the driver’s local `_currentCursor` field so that subsequent queries for `GetCursor` return the value that was set, but it must not attempt to change the physical terminal cursor.

3. **Size queries return a default** – `GetSize` (and any related methods like `GetWindowSize`) must return a safe default (80 columns × 25 rows) when no terminal is attached.

4. **Resize operations** – `ResizeBuffer` (WindowsOutput) and similar methods should either return the requested size unchanged or a default size without interacting with the console.

5. **Kitty keyboard protocol** – `EnableKittyKeyboard` and `DisableKittyKeyboard` must not write ANSI enable/disable sequences when not attached. `DisableKittyKeyboard` may still reset the local flag so that state remains consistent.

6. **Lifecycle logging** – Each driver’s constructor should log a single lifecycle message (via `Trace.Lifecycle`) indicating that no real terminal is attached and the driver is operating in degraded mode. (This replaces any existing redundant logging that may have relied on separate `Driver.IsAttachedToTerminal` calls.)

7. **Consistent detection** – All drivers must use the same property `IsAttachedToTerminal` (based on `Driver.IsAttachedToTerminal(out _, out _)`) to decide whether to suppress terminal I/O. The check should be evaluated once per instance (e.g., in `OutputBase` constructor) and then consulted by every method that would otherwise perform output or request terminal state.

**Classes involved**

- `OutputBase` — introduce the `IsAttachedToTerminal` property as the single source of truth.
- `AnsiOutput`, `NetOutput`, `UnixOutput`, `WindowsOutput` — every method that performs terminal I/O must bail out early when `IsAttachedToTerminal` is `false`.

**Rationale**

This prevents errors, unwanted escape codes in logs, and broken pipeline behavior when a Terminal.Gui application is launched in a non-interactive or redirected context.

Gracefully handle no-terminal scenarios in output drivers


**Title:** Button Text and HotKey overrides are broken; need to replace `new` with `override` and fix hotkey extraction/binding

---

### Summary
`Button` currently hides `View.Text` with `new`, breaking polymorphic access. When you hold a `Button` through a `View` reference, you get the raw text without brackets, and certain layout/draw logic doesn’t apply. Additionally, the hotkey is not automatically derived when `Text` is assigned, and the key bindings for `Space + HotKey` become stale or are not correctly maintained.

### Desired Behavior

1. **Text override instead of `new`**
   - `Button` must `override` `View.Text` so that any access via a `View` reference returns the appropriate text.
   - The override should store its own raw text (the label) and use an internal formatter to produce the bracketed display text, ensuring drawing reflects the button frame and default indicator.

2. **Automatic HotKey extraction on text change**
   - When `Button.Text` is set, automatically extract the `HotKey` from the label using the same rules as other views (first character after `HotKeySpecifier`, or first uppercase letter). If no hotkey is found, the HotKey should become `Key.Null`.
   - Setting `Text` to an empty string must reset `HotKey` to `Key.Null`.

3. **HotKey binding management**
   - The `HotKey` setter must add a key binding `Space + HotKey` → `Command.Accept` when a non-null key is assigned, and remove it when the key becomes `Key.Null`.
   - Existing bindings must be correctly transferred when the hotkey changes (replace, don’t duplicate).

4. **HotKeySpecifier synchronization**
   - `Button.HotKeySpecifier` must update the internal text formatter used for rendering so that hotkey underlining and bracket icons behave consistently.

5. **Draw behavior**
   - Override `Redraw` in `Button` to use the internal text formatter for rendering the bracketed label (including the default indicator when `IsDefault` is true) with the correct color scheme and focus/hot attributes.

6. **AutoSize support**
   - Changes to `AutoSize` must trigger a re-layout of the button so that width adjusts to the displayed text.

### Scope
Only `Button` and its interaction with `View` properties. No changes to other controls except making `View.HotKey` and `View.HotKeySpecifier` `virtual` so `Button` can override them.

---

*Behaviour not required: keyboard navigation, mouse handling, or any other button feature beyond the properties listed above.*

Changed Button Text property to use override instead of new. (#1622)


## Ticket: `KeyBindings.Add` should replace duplicate keys and register application‑scoped shortcuts

**Context:**
`KeyBindings` wraps a `Dictionary<Key, KeyBinding>` and exposes an `Add(Key key, KeyBinding binding)` method. Currently it calls `Bindings.Add(key, binding)` directly, which throws when the key already exists. Also, key bindings with `KeyBindingScope.Application` are meant to be global shortcuts, but they are never forwarded to `Application.AddKeyBinding`, so they have no effect.

**Desired behavior:**

1. **Duplicate `Key` handling** – When `Add(key, binding)` is called and a binding for `key` already exists, the new binding must **replace** the old one (instead of throwing). The resulting collection must contain exactly one binding for that key, with the commands and scope of the most recent call.

2. **Application scope registration** – If a binding is added with `KeyBindingScope.Application` (and the key is *not* already present in the collection), `Application.AddKeyBinding(key, boundView)` must be called so the shortcut works globally. If the key *already* existed, no duplicate registration should occur; the existing registration remains valid.

**Acceptance criteria:**
- `Add(key, binding)` no longer throws for a key that already has an entry; the collection reflects the new binding.
- An application‑scoped binding added to a new key becomes a functioning global shortcut (the `Application` is notified).
- Existing `Replace` method (which moves a binding from one key to another) continues to work, and its semantics are unchanged (it must remove the old key and add the new one).


I'll draft a bug report that captures the observable problem—unnecessary UPDATE queries for unchanged array columns—and the expected semantics without pointing at the exact code change.

---

**Title:** Array columns (especially date[]) always treated as changed on `repository.save()`, causing spurious UPDATE queries and @AfterUpdate triggers

**Description:**

When using TypeORM with PostgreSQL, entities that have an array column (e.g., `int[]`, `date[]`) cause an UPDATE query to be executed on every call to `repository.save()` even when the array value is identical to the value already stored in the database. This also incorrectly fires `@AfterUpdate` listeners.

The issue is especially noticeable with date array columns because the date normalization that occurs for scalar date columns is not applied to the individual elements of an array column. For example, if I save an entity with `dates: [new Date('2023-01-01T00:00:00')]` and later call `save()` with the exact same array (or even with a Date that normalizes to the same date once the time component is removed), TypeORM still generates an UPDATE statement.

**Steps to reproduce:**

1. Define an entity with a `date[]` column (or `int[]`, etc.) using Postgres.
2. Insert a row with some array value.
3. Retrieve the entity and call `repository.save()` with the same array value (or a copy with the same elements).
4. Observe that an UPDATE SQL query is issued, even though the effective database value has not changed.

**Expected behavior:**

- If the new array value normalizes to the same value as the existing database value, no UPDATE should be generated.
- Normalization rules should be applied element-wise: for `date[]`, each element should be normalized to a date string (stripping time) just as is done for scalar `date` columns; similarly for `time` and `timestamp` arrays.
- Array comparison should be based on element-wise equality after normalization, not on reference equality.
- Concretely, saving an entity with `dates: [new Date('2023-01-01')]` after having previously saved the same logical value should result in zero UPDATE queries, and `@AfterUpdate` should not fire.

**Impact:**

- Unnecessary database writes degrading performance.
- Application logic that relies on `@AfterUpdate` runs for no-op saves, leading to cascading side-effects (e.g., cache invalidations, logging, or event publishing).
- Inconsistent with the behavior of non-array date columns, which correctly skip the update after normalization.

**Environment:**

- TypeORM version: (whatever)
- Database: PostgreSQL (only Postgres supports array columns)
- Entities using array: true in column options, with types `int[]`, `date[]` etc.

This behavior makes it impossible to use array columns with optimistic updates or idempotent saves without manually guarding the update logic. The fix should ensure that array columns participate in the same normalization and deep-comparison logic that scalar columns currently benefit from.

fix: change how array columns are compared on column changed detection (#11269)


When using `repository.update` (or an `UpdateQueryBuilder`) to update an entity that has both a relation (e.g., `@OneToOne` + `@JoinColumn`) and an explicit column property that maps to the same physical database column, the generated `UPDATE` statement includes the column twice in the `SET` clause. This causes a database error (duplicate column assignment).

The problem occurs when the provided update values contain both the related entity and its foreign-key field — for example, `{ user, userId }` where `user` uses a join column named `user_id` and `userId` is a direct `@Column` mapped to `user_id`.

The update expression builder should deduplicate columns so that each physical column appears at most once in the `SET` clause, regardless of how many entity properties map to it.

fix: discard duplicated columns on update (#8724)


```
Title: PostgreSQL: Enum default with custom enumName in a schema causes unnecessary schema sync changes

Description:
When using a PostgreSQL enum column with a custom `enumName` and the entity is placed in a non-default schema (via `@Entity({ schema: "some_schema" })` or similar), every schema synchronization or migration generation incorrectly detects a change and produces queries to drop and recreate the default value—even though the schema has not actually changed.

Steps to reproduce:
1. Define an entity that includes a column of type `"enum"` with an explicit `enumName` and a `default` value, and assign the entity to a specific schema.
2. Run the initial schema sync or migration generation to create the schema.
3. Run the sync/generation again without making any modifications.

Actual result:
The second run produces non-empty up/down queries (e.g., `ALTER TYPE …` or `ALTER TABLE … ALTER COLUMN … SET DEFAULT`), indicating a phantom change.

Expected result:
No changes should be detected; the generated queries should be empty.

Additional context:
The issue appears to be in the Postgres driver’s handling of raw column defaults during table loading. When an enum is schema-qualified, the column default returned by the database contains a cast suffix such as `::some_schema.my_enum`. The logic that strips the type cast does not account for the dot (`.`) in the schema-qualified type name, leaving part of the cast behind. As a result, the normalized default kept by TypeORM (e.g., `'SOURCE_A'::some_schema.my_enum` instead of `'SOURCE_A'`) differs from the configured default, and a diff is falsely detected on every sync.
```

fix: Postgres enum generates unnecessary queries on schema sync (#8268)


When filtering by relation count via `MoreThanOrEqual` or `LessThanOrEqual` find operators in a `where` clause, the generated SQL does not include the correct `>=` / `<=` comparison.  For example:

```ts
connection.createQueryBuilder(Post, "post")
  .setFindOptions({
    where: {
      tags: MoreThanOrEqual(2)
    }
  }).getMany()
```

The returned results are incorrect; only posts that match an exact count are returned instead of those with at least 2 tags.  The equivalent queries using `MoreThan` and `LessThan` (without “OrEqual”) work correctly, producing `>` and `<` in the generated SQL subquery.

Please fix the query building so that `MoreThanOrEqual` and `LessThanOrEqual` are treated as `>=` and `<=` respectively when filtering on relations, consistent with the existing handling of `MoreThan` and `LessThan`.

fix: support More/LessThanOrEqual in relations  (#9978)


```
Title: Add `And` combinator for `FindOperator` to combine conditions on a single column

Currently, `FindOptions` supports combining multiple conditions on a column implicitly as AND when using object syntax, but there is no way to explicitly combine `FindOperator` instances (e.g., `MoreThan`, `LessThan`, `IsNull`, `Not`, etc.) with AND logic for a single field. The existing `Or` operator combines multiple operators with OR, but a corresponding `And` operator is missing.

Users need to express filter conditions like:
```
{ money: And(Not(IsNull()), MoreThan(10), LessThan(100)) }
```
This should produce a WHERE clause that effectively selects rows where `money IS NOT NULL AND money > 10 AND money < 100`. Without `And`, users are forced to drop down to `Raw` or split conditions across multiple columns, which is less composable.

Requirements:
- Provide a `And` function that accepts a variable number of `FindOperator` objects and returns a `FindOperator` with type `"and"`.
- The `And` operator must be recognized by the query builder and SQL generation layers so that it correctly produces `condition1 AND condition2 AND ...` in the generated SQL.
- The implementation should follow the existing patterns used by `Not`, `Or`, etc. — reusing existing `FindOperator` and predicate infrastructure where possible.
- The operator must be exported from the public API so that it is available to consumers of the library.
- The operator should work across all supported database drivers.
```

feat: "And" operator in FindOptions (#9489)


When `entitySkipConstructor` is enabled, the metadata validation performed during connection setup should not invoke entity constructors. Currently, an entity with a mandatory constructor parameter (e.g., one that throws if a required property is undefined) prevents connection creation even with `entitySkipConstructor: true`, because the validator creates an uninitialized instance without honoring the skip-constructor setting. The validation should use the same constructor-skipping instance creation path that deserialization uses, so that entities with guarded constructors can be used when the option is active, while still running the constructor when the option is disabled or absent.

fix: make EntityMetadataValidator comply with entitySkipConstructor, cover with test (#8445)


When multiple views are changed in a single schema sync, the generated migration does not drop all of the old views — some views are silently skipped. The resulting migration is incomplete, leaving stale view definitions in the database and causing errors when the views are later recreated. Ensure the migration generation correctly identifies and drops every view that needs to be replaced, so that all changed views are properly recreated in the same migration.

fix: Incorrect migration generated when multiple views are updated in a single migration (#7587)


```
Title: Redundant unique constraint on primary key column for one-to-one relations generates unnecessary migrations

Description:
When an entity has a one-to-one relationship where the join column is also a primary key (using @PrimaryColumn together with @JoinColumn), TypeORM’s schema builder creates a unique constraint on the foreign key column on top of the primary key. Because the column is already part of the primary key—which is inherently unique—the additional unique constraint is redundant.

This causes two concrete issues:

1. After the initial migration and schema creation, subsequent `schemaBuilder.log()` calls still produce pending "up" queries that attempt to add the same unique constraint. This results in spurious migration generation—the tool reports changes where none exist.
2. Some database engines (e.g., Oracle) reject having both a primary key constraint and a unique constraint on the same column, leading to runtime creation errors.

The problem is not driver‑specific; any SQL dialect can be affected when the schema builder emits a unique constraint for join columns that are already covered by the primary key.

Steps to reproduce:
- Define two entities with a @OneToOne relationship.
- On the owning side, mark a column with @PrimaryColumn and @JoinColumn.
- Generate the schema once, then inspect subsequent schema differences (e.g., via migration generation or `schemaBuilder().build()` followed by `schemaBuilder().log()`).
- Observe that a duplicate unique constraint is reported even though the primary key already guarantees uniqueness.

Expected behavior:
- The unique constraint should be skipped if every join column is already part of the primary key.
- The unique constraint should only be emitted for one‑to‑one relations, because only they require an explicit uniqueness guarantee on the foreign key to enforce the one‑to‑one relationship at the database level. Many‑to‑one relations do not need this constraint.
- This logic should apply consistently to all supported SQL dialects.

Acceptance criteria:
- Using @PrimaryColumn on a @OneToOne relation’s join column no longer creates a redundant unique index on that column.
- For a @ManyToOne relation, no unique constraint is generated on the join columns.
- Schema differences after the initial creation are empty (no spurious migration queries).
- The change is dialect‑agnostic and does not introduce dialect‑specific conditionals.
```

fix: prevent unique index identical to primary key (all sql dialects) (#9940)


```
Fix: Eager-loaded relations overwrite manually specified nested relations

When an entity has an eager relation (e.g., User.profile) and a query also explicitly
requests a nested relation (e.g., Editor → User → nestedProfile), the eager-loading
step assigns the eager relation's data after the manual relations have already been
populated. This causes the entire property to be replaced, losing the manually loaded
nested entities.

Expected behavior: if the property already holds an object (i.e., the entity already has
some relations loaded), the eager-loaded value should be deep-merged into it, preserving
any existing keys that the eager load does not provide. If the property is not yet set
(null or undefined), the eager value can be assigned as before.

This is especially noticeable when combining `eager: true` on a relation and the
`relations` option in find methods, but the fix should be general: any situation where a
relation value is set on an entity that already has a (non-null) object value should
merge rather than replace to avoid silently dropping data.
```

fix: prevent eager-loaded entities from overwriting manual relations (#11267)


Add support for passing `conflictPaths` as an object whose keys are entity property names in the `upsert` options. Currently `conflictPaths` only accepts an array of property-path strings. Accepting an object like `{ author: true, title: true }` would give better TypeScript autocompletion and readability. The runtime behavior should match passing the corresponding array of property keys.

feat: upsert options conflictPaths as Entity keys (#9365)


As a TypeORM user, I need to using `createQueryBuilder().relation(Post, "categories").of(post).remove(someCategory)` with a ManyToMany relation. When I pass an entity object (e.g., a `Category` instance) to `.remove()`, the entity is not removed from the relation; instead, the operation either fails silently or produces incorrect SQL. By contrast, when I pass a raw numeric ID to `.remove()`, the relation is correctly broken.

The same `.add()` method handles both entity objects and numeric IDs without issue. This inconsistency is surprising – `.remove()` should accept entity objects and extract their primary key values automatically, just as `.add()` does. The current behavior forces me to manually extract IDs, which breaks the abstraction and makes the API harder to use.

Please fix the `remove` operation for ManyToMany relations so that it correctly handles entity objects (not just raw IDs), matching the behavior of `add`. No other relation types or query-builder methods should be affected.

fix: createQueryBuilder relation remove works only if using ID (#2632) (#4734)


---
name: Fix cache writes with replication enabled
about: "Cache entries are not persisted when replication (master/slave) is enabled because writes are sent to a slave connection"
labels: bug, cache, replication
---

**Description**

When TypeORM is configured with read/write replication (master + slaves), the query result cache stops working: entries that should be cached are never actually written, or writes fail silently. This means repeated queries that should hit the cache are re-executed against the database each time.

**Root cause analysis**

Cache entries are stored by executing INSERT/UPDATE statements. In a replicated setup, if the query that triggers a cache write happens to use a slave query runner, that same slave runner is reused for the cache write. Since slaves are typically read-only, the write is rejected or does not take effect. This causes the cache to appear empty or stale on subsequent reads.

**Desired behavior**

Cache writes (i.e., the operations inside the store-in-cache logic) must always go to a **master** connection, never to a slave. In particular:

- If **no** query runner is provided to the cache writer, a new master runner must be created, used, and released after the write completes.
- If a **slave** query runner is provided, it must **not** be used for writing; instead a new master runner must be created and released for the cache write.
- If a **master** query runner is already provided, it should be used as-is and the cache writer must **not** create or release any runner (the caller retains ownership).
- The solution must work with all database drivers that support replication, and must not break drivers without replication (e.g., MongoDB), which should still satisfy the same interface contract.

**Additional constraints**

- The `QueryRunner` abstraction currently does not expose the replication mode of the runner. To implement this fix correctly without guessing, the interface needs a way to determine whether a given runner is a master or a slave.
- Any newly introduced interface method must be implemented by all concrete `QueryRunner` implementations, including `BaseQueryRunner` (which already holds the mode internally) and `MongoQueryRunner` (which should report `'master'`).
- The cache writer must not leak runners: when it creates a temporary master runner, it must release that runner after the cache operation. When it reuses a caller-supplied master runner, it must **not** release it.

**Related**

Issue reported as #5919.

fix: db caching won't work with replication enabled (#7694)


**Title:** Postgres one-to-one with `@PrimaryColumn` + `@JoinColumn` causes redundant unique constraint and repeated migration diffs

**Description**

When defining a one-to-one relationship where the owning side uses `@PrimaryColumn()` and `@JoinColumn()` on the same column (a shared primary/foreign key pattern), the generated schema includes a redundant UNIQUE constraint on a column that is already the primary key. This causes `synchronize` / migration generation to produce stale diffs: running migration generation a second time produces the same ALTER TABLE statements it just applied, because the extra unique constraint is re-detected as missing.

**Steps to reproduce**

1. Define two entities with a one-to-one relationship.
2. On the owning entity, annotate the join column property with both `@PrimaryColumn()` and `@JoinColumn()`.
3. Point TypeORM at a fresh Postgres database.
4. Run `synchronize: true` or generate a migration, then generate again immediately afterwards.

**Expected behavior**

Running schema sync or migration generation a second time should produce zero pending changes. A column that is already a primary key should not also receive a standalone UNIQUE constraint, since the primary key constraint already guarantees uniqueness.

**Environment**

- Database: PostgreSQL
- TypeORM version: latest
- Entity pattern: `@PrimaryColumn` + `@OneToOne` + `@JoinColumn` on the same field

**Additional context**

Oracle apparently already has handling to skip the redundant unique constraint in this exact situation (likely because Oracle disallows both a primary key and a unique constraint on the same column). The same logic should apply to Postgres, which also rejects creating a unique constraint alongside a primary key during table creation (and a primary key is already unique anyway).

fix: redundant Unique constraint on primary join column in Postgres (#9677)


**Bug Report: Saving an entity with `persistence: false` relations and shared join columns throws error when relations are eagerly loaded**

**Description**
If an entity defines multiple `@OneToOne` or `@ManyToOne` relations that share the same foreign key column (via `@JoinColumn({ name: ... })`) and those relations are marked with `persistence: false`, calling `save()` on the entity fails when the relations are eagerly loaded (e.g., loaded via the `relations` option in `find`). The same operation succeeds when those relations are not loaded or are loaded lazily.

**Steps to Reproduce**
1. Define an entity with two `@OneToOne` relations pointing to different tables, both using the same join column (e.g., `option_id`). Mark both relations with `{ persistence: false, lazy: true }` (or just `persistence: false`).
2. Load the entity using `findOne` with `relations: { optionA: true, optionB: true }` to eagerly fetch both relations.
3. Call `save()` on the loaded entity.
4. Observe that TypeORM throws an error during the save operation.

**Expected Behavior**
Relations with `persistence: false` should be entirely ignored during the change-detection phase of a save operation. They should not be inspected for changed values, as TypeORM is not responsible for persisting them. The presence or absence of eager loading should not affect this behavior.

**Impact**
This bug prevents using shared columns for polymorphic/discriminated relationships while still allowing eager loading for read purposes. Users are forced to avoid eager loading or manually detach `persistence: false` relations before every save, which is error-prone and defeats the purpose of the ORM abstraction.

**Additional Context**
The error likely stems from the part of the save pipeline that computes which relational columns have changed, where relations with `persistence: false` are not being excluded. The fix should ensure that all relations with `persistenceEnabled === false` are skipped during that computation, regardless of their load state.

fix: fix up save with eagerly loaded relation (#11975)


**Title:** `@RelationId` on nullable bigint relation returns string `"null"` instead of `null`

**Description**

When an entity has a nullable relation whose primary key type is `bigint` and the relation is annotated with `@RelationId`, loading an entity where the relation is `null` populates the `@RelationId` property with the string `"null"` instead of JavaScript `null`. Additionally, in some scenarios the property is incorrectly excluded altogether rather than being set to `null`.

**Expected Behavior**
- If the relation is `null`, the property decorated with `@RelationId` should be `null` (the JavaScript primitive), not the string `"null"`.
- The `@RelationId` property should always be present on the loaded entity—either a string when a relation is set, or `null` when the relation is missing.
- The existing bigint‑to‑string conversion that applies to bigint primary keys should **not** be applied to `null` values.

**Example**
```typescript
@Entity()
class Child {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  id: string;
}

@Entity()
class Parent {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  id: string;

  @OneToOne(() => Child, { nullable: true })
  @JoinColumn()
  child: Child | null;

  @RelationId((parent: Parent) => parent.child)
  childId: string | null;    // should be null when no child is attached
}
```
When a `Parent` row has `childId` as SQL `NULL` in the database, calling `find`/`findOne` should yield an entity where `parent.childId === null`.

**Environment**
TypeORM current master / any version with bigint `@RelationId` support.

fix: return null for nullable RelationId() column (#6848)


**Title:** Codemod: scope and type‑name detection misses barrel files, namespace‑qualified types, and foreign‑namespace references

**Description:**
The codemod transforms (e.g. `connection‑to‑datasource`, `repository‑find‑by‑ids`) rely on a handful of AST helpers to decide whether to process a file and how to classify TypeScript type references. Several AST shapes that appear in real codebases are not handled, leading to skipped rewrites and false‑positive transformations.

**1. Barrel files are skipped**
Files that *only* re‑export TypeORM APIs (e.g. `export { Connection } from "typeorm"`; `export * from "typeorm/driver/…"`) contain no `import` statement. The `fileImportsFrom` guard currently only looks at `import` / `require` / `import = require(…)` forms, so barrel files are excluded from all transforms. The guard should also recognise ESM `export … from` and `export * from` sources that point at a TypeORM module or sub‑path.

**2. Namespace‑qualified type references are invisible**
When a user writes `import * as typeorm from "typeorm"` and uses `typeorm.Repository<User>` in parameter or variable type annotations, `getTypeReferenceRootName` does not unwrap the `TSQualifiedName` inside the `TSTypeReference`. Consequently bindings typed with qualified references are not recognised as Repository/DataSource receivers, and their method calls (e.g. `.findByIds`) are left untouched.

**3. False‑positive classification from foreign namespaces**
In a file that imports both `import * as typeorm from "typeorm"` and `import * as Foo from "some‑other‑lib"`, a parameter typed `Foo.Repository<User>` has the same rightmost name `Repository`. Without checking which namespace the qualifier belongs to, the helpers treat such bindings as TypeORM receivers and may incorrectly rewrite their method calls. The type‑name resolution must accept qualified references only when the leftmost identifier matches one of the known TypeORM namespace imports.

**4. Invalid augmentation of namespace‑only type imports**
The `connection‑to‑datasource` transform tries to add `DataSourceOptions` to an existing `import type { … } from "typeorm"`. If the file already has `import type * as Typeorm from "typeorm"` (or a default‑only type import), pushing a named specifier produces invalid TypeScript. In those cases the transform should fall back to emitting a fresh `import type { DataSourceOptions }` line instead of corrupting the existing declaration.

**5. CLI diagnostic failures mask original errors**
When `runOneTransform` tries to print buffered worker output after an error and the print itself throws (e.g. EPIPE), the exception is silently swallowed and the original transform error may never reach the caller. Instead, the tool should write a brief warning to `stderr` (with its own EPIPE guard) and then rethrow the original error so that the real failure is visible.

**Acceptance criteria**
- Barrel files that only re‑export TypeORM APIs are processed by all transforms.
- Parameters and variables typed with qualified TypeORM names (`typeorm.Repository<T>`) are recognised as receivers, and their method calls are rewritten appropriately.
- Qualified type references rooted at a non‑TypeORM namespace are *never* treated as TypeORM receivers.
- `import type * as X from "typeorm"` is left intact; `DataSourceOptions` is added through a separate import line.
- CLI diagnostic failures no longer mask the original transform error.

fix(codemod): harden scope and type-name detection across more AST shapes (#12394)


```
Title: Add a naming strategy for legacy Oracle databases with 30‑byte identifier limit

Description:
When TypeORM is used with older Oracle databases that enforce a 30‑byte identifier limit,
creating tables that have long column names fails with ORA-00972.
We need a new naming strategy that can be configured on a DataSource to automatically
shorten generated column names so they never exceed 30 characters.

The strategy should support two shortening behaviours selectable at construction time:
- “truncate” — keep the first 30 characters of the original name.
- “hash” — replace the name with a short deterministic hash of the original name
  (prefixed with a short constant so the names remain human‑distinguishable).

The new strategy must extend the existing `DefaultNamingStrategy` and implement
`NamingStrategyInterface`, and it must be publicly exported from the main package.
For now, only column names need to be shortened; other identifier limits have already
been addressed elsewhere.

When a user does not explicitly choose a shortening behaviour, the strategy should
default to “hash”.

The implementation must be compatible with TypeScript and the existing Oracle driver,
and it must not break any existing naming‑strategy contracts.
```

feat: naming strategy for legacy Oracle (#9703)


When using `Repository.find`, `findOne`, or QueryBuilder conditions with an object like `{ id: value }` on an entity that has a column whose database name overlaps with the property name of a different column, the generated SQL uses the wrong database column.

For example, given an entity:

- `oldId` (primary, database name `"id"`)
- `id` (regular, database name `"new_id"`)

Calling `repository.find({ where: { id: something } })` incorrectly resolves `id` to the database column `"id"` (which belongs to `oldId`) instead of `"new_id"` (which belongs to the `id` property). The expected behavior is that the entity's `id` property always maps to its own database name (`"new_id"`) in query conditions, never to a database name that happens to match another column's property name.

The fix must ensure that property-name references in find/where options are not collided by overlapping database names or property paths of other columns. After the fix, the entity's own property names should be resolved to their corresponding database column, even when a different column's database name equals that property name. The same correct precedence should apply to all property-path, property-name, and database-name substitutions performed by the QueryBuilder.

fix: handle overlapping property / database names in querybuilder (#7042)


```
**Title:** MSSQL: where-condition parameters missing type information, causing query errors

**Description:**
When using TypeORM with an MSSQL connection, queries that contain where conditions fail because the database driver receives parameters without the required type metadata. Reproduced with `repository.find({ where: { memberId: 'abc' } })` on MSSQL — the generated parameter lacks column-type information and the MSSQL driver throws an error or returns incorrect results.

**Expected behavior:**
Where-condition parameters for MSSQL should be wrapped in typed parameter objects (mirroring the column’s type/varchar/etc.) so the MSSQL driver executes the query correctly. The behavior for non-MSSQL databases (e.g., PostgreSQL) must remain unchanged — they should continue to receive plain parameter values.

**Edge cases / constraints:**
- The fix must apply to plain scalar values as well as to values inside `FindOperator`s (e.g., `Not`, `LessThan`), with the exception of `Raw` operators — raw operator values should **not** be re‑wrapped, as they are already complete expressions.
- The conversion should happen late enough that any prior column‑transformer application is preserved.
- The change must be scoped to MSSQL connections only; other connection types must not be affected.

**Impact:**
Currently, using `find` with a simple where condition against an MSSQL database is broken. This prevents migration of existing TypeORM projects to MSSQL and makes even basic CRUD operations unreliable.
```

fix: ensure correct MSSQL parameter conversion in where conditions


Improve JSON diagnostic messages:

- When parsing a JSON string fails, report the line and column number of the error instead of the raw byte offset.
- When loading a JSON file fails, include the file path in the error message.
- When the TaxiConfig bootstrap loader fails to load a bootstrap file, include the bootstrap file name in the error message.

feat core: improve JSON diagnostic (#1818)


**Title:** `kNotRequired` components ignore their static config when one is provided

**Description**
Components marked with `ConfigFileMode::kNotRequired` are intended to work without a configuration section in the static YAML file, but when a section *is* supplied it should be used as the component’s config. Currently, any such section is ignored and the component always receives an empty configuration that contains only the schema defaults.

The root cause is in `Manager::MakeComponentConfigMap`: the map is first populated with empty default configs for every `kNotRequired` component, and later the actual config entries from the parsed YAML are inserted. Because the map uses `emplace`, the earlier empty entries take precedence and the real config is discarded.

**Expected Behavior**
- If a `kNotRequired` component has a matching section in the static config YAML, that section must become the component’s `ComponentConfig`.
- If no section is present, the component should still receive an empty config so that schema defaults apply (existing behavior for the missing-section case).
- The change must not affect components with `ConfigFileMode::kRequired` (they already require a section).

**Acceptance Criteria**
1. A `kNotRequired` component that defines a property with a default (e.g., `greeting: default`) reads an explicit value from the static config when one is set (e.g., `greeting: custom`).
2. When the static config omits the component section entirely, the component still sees the schema default.
3. No regression for `kRequired` components.

bug components: don't ignore static config for kNotRequired components


Title: Multiple Cookie headers are incorrectly merged using comma instead of semicolon

Description:
When an HTTP request contains multiple `Cookie` header fields (as allowed by RFC 6265), the framework merges their values using a comma (`,`) delimiter. However, according to RFC 6265 §5.4, multiple `Cookie` headers must be joined into a single header value using a semicolon followed by a space (`; `). The current comma-based concatenation produces a malformed cookie string that the cookie parser cannot interpret correctly.

Steps to Reproduce:
1. Send an HTTP request with two `Cookie` headers, e.g.:
   ```
   GET / HTTP/1.1
   Host: example.com
   Cookie: a=1; b=2
   Cookie: c=3; d=4
   ```
2. Observe the parsed cookies (via `HttpRequest::GetCookie()` or `CookieCount()`).

Actual Behavior:
- The two header values are joined as `"a=1; b=2,c=3; d=4"`.
- The cookie parser treats the comma as part of a cookie name or value, resulting in:
  - `"a"` = `"1"` (incorrectly including the `;` after `a`? Actually depends on parsing)
  - `"b"` = `"2,c=3"` (the comma corrupts the value)
  - The cookies `c` and `d` are lost or misidentified.
- `CookieCount()` returns a wrong number (likely fewer than 4), and `GetCookie("b")` returns an unexpected value.

Expected Behavior:
- The two values should be combined as `"a=1; b=2; c=3; d=4"` (using `; `).
- The parser should correctly recognize four cookies: `a=1`, `b=2`, `c=3`, `d=4`.
- `CookieCount()` should return 4 and each `GetCookie()` call should return the correct value.

Impact:
- Applications relying on multiple `Cookie` headers (e.g., some proxies or user agents that split long cookies) will have broken cookie handling, leading to authentication failures, session mismatches, or missing data.
- The behavior violates RFC 6265 and breaks interoperability with compliant HTTP clients.

Desired Fix:
In the header-map merge logic (when appending values for the same header name), the `Cookie` header must be explicitly handled: instead of the generic `,` separator, use `"; "` as mandated by the RFC. This special case should apply only to the `Cookie` header name (case-insensitively). Other headers should continue to use the comma separator.

feat userver: fix merging multiple Cookie headers


Add Prometheus exposition format support for histogram metrics.

Currently `utils::statistics::ToPrometheusFormat` and `ToPrometheusFormatUntyped` reject histograms with a fatal error. They must instead emit standard Prometheus histogram lines for each histogram in the storage:

- `metric_bucket{le="<upper_bound>"} <cumulative_count>` for every bucket, including a final bucket with `le="+Inf"`.
- `metric_count{} <total_count>`.

Cumulative counts must be computed across buckets so that each `_bucket` line reports the sum of all histogram values up to and including that bucket. The `_count` value must equal the total count across all buckets (including the inf bucket).

When labels are supplied via `Writer::ValueWithLabels`, those labels must appear in every output line together with the `le` label. For the `_count` line, only the custom labels are present (no `le` label).

feat userver / core: add histogram prometheus format


A race in `Mutex::unlock` and `Semaphore::unlock_shared_count` can cause hangs under high contention when multiple threads repeatedly acquire and release the primitive.
The root issue is that the unlock paths use `std::memory_order_release` when clearing the owner pointer or releasing lock count, which does not guarantee that a concurrent locker’s state is fully visible to the unlocker when it inspects the wait list, nor that the unlock store is visible to a subsequent fast-path lock acquisition.

### Steps to reproduce
- Run many threads contending for a single `Mutex` (or a `Semaphore` with capacity 1) for an extended period.
- Tasks occasionally timeout waiting for a lock that should be free, or the primitive appears to “miss” a wakeup.

### Expected behavior
- Unlock must synchronize with the next successful `lock` / `try_lock` so that ownership is transferred without a window where both the old and new owner believe they hold the lock.
- Unlock must also see any waiter that commits to sleeping before the unlock inspects the wait list, so that no waiter is left sleeping indefinitely.

### Proposed fix
1. In `Mutex::unlock`, change the atomic exchange on `owner_`:
   - from `exchange(nullptr, std::memory_order_release)`
   - to `exchange(nullptr, std::memory_order_acq_rel)`.
2. In `Semaphore::unlock_shared_count`, change the atomic fetch-add on `remaining_simultaneous_locks_`:
   - from `fetch_add(count, std::memory_order_release)`
   - to `fetch_add(count, std::memory_order_acq_rel)`.

The `acq_rel` ordering ensures that:
- The release part makes the store visible to subsequent lock acquisitions that use `acquire` semantics.
- The acquire part makes any prior stores from a concurrent locker visible to the unlocker before it checks the wait list.

### Additional testing
Expand the `Mutex` test suite to also cover `SharedMutex` (which builds on `Mutex`/`Semaphore`) and add a stress test for lock passing:
- Multi-threaded scenario where `kThreads` tasks repeatedly acquire and release the lock for a fixed duration (e.g., 500 ms) without deadlines or sleeps inside the critical section.
- The test should assert that every `try_lock_for` with a generous timeout succeeds within that interval, ensuring no thread is starved or left hanging.

Implement an analogous stress test for `Semaphore` as well.

**Relates: TAXICOMMON-3061**

bug engine: fix Mutex unlock race (#1620)


## Request: Gracefully handle `prepared statement already exists` after prepare timeout

### Context
When a PostgreSQL prepare request times out (e.g. due to a network delay), the driver may discard the statement from its local cache, but the server may still have the prepared statement from the original (timed-out) request.

On a subsequent use of the same connection – or after the connection is released and reused – the driver attempts to prepare the same statement again. The server responds with a `prepared statement already exists` error (SQLSTATE `42P03`). Currently this error is treated as a fatal failure; the connection can become broken, the query fails, and the driver does not recover.

### Desired behavior
1. **Recover from duplicate prepare on timeout**
   When sending `SendPrepare` and the subsequent `WaitResult` raises a `DuplicatePreparedStatement` exception:
   - The driver should **not** re-prepare the statement.
   - Outside a transaction, it should simply proceed to describe and execute the already-existing server-side prepared statement.
   - Inside a transaction, the transaction is aborted; the driver should throw and let the transaction roll back.

2. **Re-describe without re-preparing**
   If the internal statement cache contains an entry for the query (i.e., the statement name is known) but the entry holds no valid description (e.g. the original `DescribePrepared` was never completed or the description was lost), the driver should:
   - **Skip** the `SendPrepare` call entirely.
   - Still issue `DescribePrepared` to obtain or refresh the description.
   - Update the cache with the new description and proceed normally.

   This avoids a second `prepared statement already exists` error entirely.

3. **Logging classification**
   The SQLSTATE `42P03` (`DuplicatePreparedStatement`) must be classified as a warning, not as an error. It should not be logged at `LOG_ERROR` level, to prevent false alarms.

4. **Connection pool safety**
   When a connection is released back to the pool while in a busy state (e.g. after a timeout), the cleanup routine must be safe and not crash or corrupt state. Any testpoints that assist in verifying cleanup ordering are acceptable, but the driver must remain stable during such cleanup.

### Constraints
- The fix must not change the semantics for normal, non-timing-out prepare flows.
- The existing prepared statement cache eviction logic (max size, least-used) must still work correctly when an entry is missing a description.
- The fix applies to the internal `ConnectionImpl::DoPrepareStatement` method and related logic; no changes to public API are required.

bug postgres: failover after "prepared statement already exists"


We need the WebSocket client to properly handle HTTP handshake failures (e.g., 401, 403) as handshake rejections rather than connection errors. Currently, when the server returns a non‑101 status during the WebSocket upgrade, the client treats the entire request as a connection failure and the caller cannot access the HTTP response. Instead, `PerformWebSocketHandshake()` should return a `WebSocketResponse` where `IsProtocolUpgraded()` is false and the caller can inspect the status code, headers, and body via `GetHandshakeResponse()`. The client must not propagate a curl-level “HTTP returned error” as a fatal error when a complete HTTP response with a finite status code was received. Additionally, `MakeWebSocketConnection()` must throw (or at least reliably indicate an error) when called on a response that did not upgrade to WebSocket, or when the internal socket has already been extracted.

feat userver: handle non-101 HTTP responses in WebSocket handshake


Title: Add `#file` suffix to YamlConfig for loading configuration values from files

Background
Currently YamlConfig can read environment variables via keys ending in `#env` when constructed with `Mode::kEnvAllowed`. There is no equivalent for reading file contents, which would be useful for secrets that are mounted as files (Docker secrets, Kubernetes secrets, encrypted volumes). This is especially needed for the core ComponentsManager so that component configurations can reference external files.

Request
Add a new `YamlConfig::Mode` variant `kEnvAndFileAllowed` that enables both `#env` and a new `#file` suffix.

When a key `some_key#file` is present and the mode allows it:
- The value of `some_key#file` is treated as a path to a file.
- The file is read and the content is parsed as YAML (using `formats::yaml::blocking::FromFile`).
- If the file does not exist or cannot be read, the lookup should behave as if the value were missing and proceed to the next step in the fallback chain.

Fallback chain resolution order for a key `some_key` must be:
1. `$variable` substitution from `config_vars`.
2. Environment variable from `some_key#env` (if mode allows env).
3. File content from `some_key#file` (if mode allows file).
4. Explicit `some_key#fallback` value.

If the mode does not allow file reading (i.e. `kSecure` or `kEnvAllowed`), any attempt to resolve a `#file` suffix must throw an exception with a clear message.

Additional requirements:
- The ComponentsManager must use `kEnvAndFileAllowed` so that all components can leverage `#file` in their static config.
- Update existing YAML config documentation (the class header) to describe `#file` and its fallback behaviour.
- Extend the static config validator to ignore the `#file` suffix in the same way it currently ignores `#env` and `#fallback`.
- Security note: the feature must only be used on configs from trusted sources, similar to the existing environment variable feature.

Implementation hints:
- Add helper functions `GetFileName(key)` and `GetFromFileImpl(...)` analogous to the existing env helpers.
- Use `boost::filesystem::exists` to detect missing files gracefully.
- Ensure nested substitutions are stripped when a value is resolved via a file (yield a secure sub-config).

References:
- Issue #548

feat core: allow reading files from YamlConfig in ComponentsManager


**Summary:** Parsing deeply nested JSON causes stack overflow or excessive memory consumption, leading to crashes. A depth limit should be enforced during parse, and an exception raised when exceeded.

**Steps to reproduce:**
1. Construct a JSON string containing thousands of nested objects or arrays (depth > ~200).
2. Call `formats::json::FromString()` or any of the streaming/SAX parsers with that input.

**Actual behavior:**
- The process crashes with a stack overflow (segfault) or hangs consuming extreme amounts of memory.
- No error is reported to the caller; the server aborts.

**Expected behavior:**
- A maximum allowed nesting depth (e.g., 128) is enforced.
- When the depth exceeds the limit during parsing, a `ParseException` (or `BaseError` subclass) is thrown with a clear message indicating the limit.
- The limit applies to both object and array nesting, counting each opening `{` or `[`.
- After the exception, no internal parser resources leak (e.g., `rapidjson::GenericDocument` stack is cleaned up).
- The depth limit is the same constant used in `CheckKeyUniqueness` (serialization path) so behavior is consistent.

**Impact:**
- Denial-of-service vector: an attacker can send a short payload that triggers deep recursion, crashing the service.
- Memory exhaustion if the parser manages to allocate before overflowing.
- Currently, no safeguard prevents this in the core `FromString`/`FromStream` or the SAX-based parsers (`ParserState`).

**Additional context:**
- The serialization path already has a `kJsonDepthLimit` check in `CheckKeyUniqueness` (serialize.cpp), but parsing lacks an equivalent bound.
- Two parsing code paths need the limit: the direct `JsonValueParser` (StartObject/StartArray methods) and the SAX-based `ParserState::ProcessInput` (stack depth tracking).
- After depth-exceeded exception, `rapidjson::GenericDocument`’s internal stack must be unwound; otherwise the parser leaks memory. A destructor or cleanup in `JsonValueParser::Impl` would be required.


## Bug: Imported binding in computed destructuring key is not rewritten during SSR transform

When Vite’s SSR transform processes a module, imported bindings are rewritten to explicit references (e.g., `import { foo } from 'mod'` → `const foo = __vite_ssr_import_0__.foo`). However, if an imported binding is used as a **computed property key inside a destructuring pattern**, the rewrite is skipped, leaving the original identifier in the output. This produces a runtime error because the identifier is no longer defined after transformation.

### Steps to reproduce

```js
// source
import { key } from './module.js'

const obj = { /* ... */ }
const { [key]: localAlias } = obj
```

After SSR transform, the output incorrectly keeps `key` in the destructuring:

```js
const __vite_ssr_import_0__ = await __vite_ssr_import__("./module.js")
const { [key]: localAlias } = obj
//      ^^^ ReferenceError: key is not defined
```

### Expected behavior

The computed key identifier `key` (an imported binding) must be replaced with the corresponding import reference. The local binding `localAlias` (the value side of the destructuring property) must **not** be rewritten, as it declares a new variable.

Correct output:

```js
const { [__vite_ssr_import_0__.key]: localAlias } = obj
```

Shorthand destructuring (`{ key }` → `{ key: __vite_ssr_import_0__.key }`) should continue to work normally.

### Scope of the fix

- Any destructuring pattern (object destructuring in variable declarations, assignments, or function parameters) that contains a computed property key referencing an imported identifier should be handled.
- The `value` side of the pattern (the new binding) must be ignored for rewriting.
- Regular (non-destructuring) object expressions with computed keys that reference imported identifiers must still be rewritten correctly (no regression).
- The same logic should apply to computed keys in object methods and arrow function properties (ensured by existing coverage).

### Non‑obvious constraints

- The destructuring property node’s `key` can be an identifier or a more complex expression. Only `Identifier` nodes that are imported bindings should be rewritten; if the computed key is a literal or a local variable, it must be left unchanged.
- The `value` of a destructuring property (which may be another pattern) must not be treated as an import reference, even if it shares the same name.
- Assignment destructuring (`({ [key]: value } = obj)`) must follow the same rule.
- Deeply nested patterns and mixed shorthand/alias usage should remain unaffected.

fix(ssr): rename objectPattern dynamic key (fixes #9585) (#9609)


## Feature Request: Allow workers to be named via constructor options

When using Vite’s web worker imports (e.g., `new Worker()` via `?worker`, `?worker&inline`, `?sharedworker`, `?sharedworker&inline`), the generated constructor currently does not accept any options. This means developers cannot set the `name` property of the resulting `Worker` or `SharedWorker` instance, which is important for debugging in browser DevTools.

We need to extend the worker constructor signatures so that a `name` can be passed through to the native API.

### Acceptance Criteria

1. **Named workers in development and production**
   Given a Vite project that imports a worker using any of the supported query parameters (`?worker`, `?worker&inline`, `?sharedworker`, `?sharedworker&inline`),
   when I instantiate the worker like
   ```js
   const worker = new MyWorker({ name: 'my-debug-name' })
   ```
   then the underlying `Worker` (or `SharedWorker`) object should have its `name` property set to `'my-debug-name'`. This must hold for both `vite dev` and `vite build`.

2. **Works for module and classic workers**
   The name option must be correctly passed regardless of whether the worker type is `"module"` or `"classic"` (including environments where module workers are used by default).

3. **Inline workers must support naming**
   Even when the worker script is inlined (via `?worker&inline` or `?sharedworker&inline`), the name should be forwarded. Specifically, when the constructor falls back from a blob URL to a data URL or uses the data URL directly, the name option must still be included.

4. **Constructor signature in TypeScript declarations**
   The ambient type declarations (`vite/client.d.ts`) for the worker modules must reflect the new optional constructor argument. For example:
   - `declare module '*?worker'` should export a constructor that accepts `options?: { name?: string }`.
   - The same applies to `'*?worker&inline'`, `'*?sharedworker'`, and `'*?sharedworker&inline'`.

5. **Backward compatibility**
   Creating a worker without any options (`new MyWorker()`) must continue to work without change. The `name` parameter is optional; when omitted, the worker name remains unspecified (i.e., an empty string) just like before.

6. **Shared workers must work identically**
   Shared workers created from `?sharedworker` and `?sharedworker&inline` support the same `name` option, and multiple instances sharing the same `name` (and same URL) share the worker as per the spec.

7. **No regressions on existing worker features**
   All other behaviors (URL generation, asset emission, HMR, build optimizations) remain unaffected.

### Additional Context

- The `name` option should be a `string?`. Passing `undefined` or omitting the option should be equivalent to the current behavior (no name set).
- The feature is needed for better debugging of worker-intensive applications, where DevTools’ Sources panel shows worker threads only by their `name`.

feat(worker): support a way to name the worker (#14032)


When the `envPrefix` configuration option is set to a value that contains whitespace (for example, `envPrefix: 'WITH SPACE'` or `envPrefix: ['CUSTOM_', 'ANOTHER SPACE']`), Vite silently fails to load any environment variables matching that prefix. No error or warning is shown, making the misconfiguration hard to detect. Users expect the variables with that prefix to be exposed in `import.meta.env`, but they are not, leading to confusion and unnecessary debugging.

**Expected behavior**: Vite should emit a console warning (yellow text) whenever any of the `envPrefix` strings contains a whitespace character (spaces, tabs, etc.), because environment variable names cannot contain whitespace and such a prefix will never match any real variables. The warning should clearly state that the whitespace-containing prefix will not work in practice. The existing validation that throws an error for an empty string prefix should remain unchanged.

The change should affect only the `envPrefix` resolution used during both development and build. It should not block the build; it’s a non‑fatal warning (similar to other configuration hints). This will help developers catch typos and misunderstandings early, avoiding subtle failures where expected env variables are missing.

feat: warn if `envPrefix` contains spaces (#21292)


**fix(ssr): sourcemap content (fixes #8657) (#8997)**

SSR source maps currently emit `sourcesContent` that contains the final, rewritten code (including `__vite_ssr_import__` placeholders).
This makes debugging through devtools or Node inspector unusable because the displayed source no longer matches the original source code.

### Expected behavior

1. **Source map content reflects pre‑SSR code**
   For any module processed by the SSR transform, the generated source map’s `sourcesContent` array must contain the module code **as it existed immediately before the SSR transform ran** – i.e. after all other plugin transforms (TypeScript, JSX, etc.) but before SSR‑specific rewrites.

2. **Source map integrity**
   The mappings must still correctly translate positions from the SSRewritten output back to the original code.
   The `sourcesContent` value must correspond exactly to the original source bytes so that debuggers can display the right lines and column numbers.

3. **Respecting incoming source maps**
   When the module comes with an existing source map from a previous transform, the final combined source map must:
   - Use the incoming map’s `sourcesContent` for those intermediate sources if available.
   - Not overwrite the top‑level source’s content with the post‑SSR code.
   - Preserve the correct mapping chain so that the developer still sees the output of the earlier transforms, not the SSR internals.

4. **No observable regressions**
   Stack traces, error locations, and breakpoints set via SSR source maps should point to the original source text that the developer wrote (or the output of earlier compilation steps), without exposing any SSR runtime helper identifiers.

### How to verify

- Serve a project with Vite in SSR mode.
- Trigger an error inside an SSR‑transformed module.
- Open the stack trace in a debugger.
- The debugger should show the source code **without** any `__vite_ssr_import_0__`, `__vite_ssr_exportAll__`, or similar internal rewriting.
- The `sourcesContent` entry for the file in the `.map` file (or in‑memory source map) should be identical to the code that entered the SSR transform step, not its output.

### Implementation notes

- The internal `ssrTransform` function currently has no way to know the original code – it only sees the code that will be transformed.
  To fulfill the acceptance criteria, `ssrTransform` (and the dev server’s plumbing that calls it) must be able to accept the pre‑SSR code string so it can set `sourcesContent` correctly.
- All call sites (`ViteDevServer.ssrTransform` and the `transformRequest` pipeline) must be updated to pass this original code through.


**Bug: Workers broken in bundled dev mode (`experimental.bundledDev`)**

**Description**
When running the dev server with `experimental.bundledDev: true`, workers defined either via `new Worker(new URL('./worker.js', import.meta.url))` or via the `?worker` import syntax fail to load. The worker script URL is incorrect (likely a build‑time placeholder), so the worker never starts. Additionally, HMR updates are not applied when the worker source file is edited; the running worker continues to see the old content.

**Expected behavior**
- Both worker creation patterns should resolve to the actual worker bundle output and load successfully in the dev server.
- Editing a worker source file should trigger HMR, updating the worker’s behavior without a full page reload, just like other modules in bundled dev mode.

**Impact**
The entire worker feature is unusable in the experimental bundled dev mode. Users testing or developing applications that rely on workers cannot do so with `experimental.bundledDev` enabled, which blocks adoption and testing of this mode for real‑world apps with workers.

**Steps to reproduce**
1. Set `experimental.bundledDev: true` in `vite.config.ts`.
2. Create a worker file, e.g. `worker.js`, and import it either with `new Worker(new URL('./worker.js', import.meta.url))` or `import MyWorker from './worker.js?worker'`.
3. Start `vite dev` and observe that the worker fails to load (no messages posted) and that editing the worker file does not cause any update in the browser.

test(bundled-dev): add worker test cases (#21557)


## Bug Report: Manifest entry asset chunks are missing the `names` array

### Describe the bug

When multiple entry points produce the same CSS or other asset chunk (e.g., because they import the same CSS file), the `manifest.json` generated by Vite’s build does not include a `names` field for that asset chunk. Only a single `name` property is provided, which is insufficient when the asset chunk is shared among multiple original entry names.

As a result, backend frameworks that consume the manifest cannot reliably resolve asset URLs for all relevant entry points. This makes it difficult to generate correct `<link>` or `<script>` tags when several entry points depend on the same output asset.

### Expected behavior

For every **entry** asset chunk in `manifest.json`, there should be a new `names` field that is an array of strings containing **all** original entry names that map to that chunk. This would mirror the `names` array already present on Rollup’s `OutputAsset` objects.

Example manifest fragment for a shared CSS entry chunk:

```json
{
  "assets/bar-a1b2c3.css": {
    "file": "assets/bar-a1b2c3.css",
    "src": "bar.css",
    "isEntry": true,
    "name": "bar.css",
    "names": ["bar.css", "other-entry.css"]
  }
}
```

**Constraints and edge cases:**
- The `names` field should **only** be set on entry assets (where `isEntry: true`). Non-entry assets should not include it.
- The value must be exactly the `names` array provided by Rollup for that output asset, which lists the original entry point file names relative to the project root.
- If an entry asset has only one original name (the common case), the array should still be present, e.g., `"names": ["bar.css"]`.
- The `ManifestChunk` TypeScript type must be updated to include the optional `names?: string[]` property.

### Additional context

This is especially visible in the backend-integration playground and similar setups where a single CSS file is imported in multiple entry points. Without the `names` array, there is no way to programmatically know that the same built asset belongs to more than one entry. The existing `name` field only holds one name, which may not be the one the backend is looking for. Adding `names` allows full, unambiguous mapping and brings the manifest in line with Rollup’s output information.

feat(build): provide names for asset entrypoints (#19912)


**Feature request: Pre-warm module transform cache on server start to reduce initial page load latency**

When the Vite dev server starts cold, the first request for a deeply nested module graph can be slow because each file transformation must complete before its imports are discovered, creating a sequential waterfall (e.g., `main.js → Component.vue → big-file.js → large-data.json`). This results in a poor first-load experience.

### Desired behavior

Add a new `server.warmup` option that allows users to declare a set of module paths (relative to the project root) that Vite should eagerly transform and cache **immediately after the server starts**, before any browser request triggers them.

1. `server.warmup` is an object with two optional arrays of glob patterns:
   - `clientFiles` – files/modules that should be pre-transformed for client‑side consumption.
   - `ssrFiles` – files/modules that should be pre-transformed for SSR usage.

2. Warmup runs **asynchronously** after the server is ready to accept connections; the server must **not** be blocked from starting. Even if warmup is still in progress, the server should serve requests normally.

3. For each matched file that is an HTML file, Vite should run the `transformIndexHtml` pipeline (which internally transforms referenced JS/CSS modules). For all other files, Vite should perform the standard `transformRequest` (with the appropriate `ssr` flag) so that the transform result is cached in the module graph.

4. Warmup should use the configured `root` as the base directory for resolving the glob patterns.

5. If a file cannot be transformed (e.g., missing, syntax error), a descriptive error should be logged, but the server must **not** fail to start, and warmup should continue with the remaining files.

6. Only files that are under the project root (or accessible via `/@fs/`) should be processed; files outside the root that are specified via an absolute path are still allowed via `/@fs/` as usual.

### External constraints

- Existing paths must continue to work without warmup; the feature is opt‑in.
- Warmup must not cause module invalidation issues or interfere with HMR (changes to a warmed file after startup should still trigger HMR normally).
- The warmup process must be implemented efficiently so that adding many files does not significantly delay the server’s “ready” state (queue-based, non‑blocking).


**Title:** SSR dev server throws `SyntaxError` for property access on namespace imports

**Description:**
When using `import * as ns from 'some-module'` in server-side rendered code, accessing any property on `ns` that is not statically known as an export (e.g. `ns.foo`) causes Vite’s SSR engine to immediately throw:

```
SyntaxError: [vite] The requested module 'some-module' does not provide an export named 'foo'
```

This happens even though the JavaScript specification allows namespace imports to expose `undefined` for non‑exported properties – the namespace object is not required to throw at access time. The error is triggered by Vite’s internal proxy guard that checks every property access against the module’s actual exports.

**Expected behavior:**
Namespace imports (`import * as ns from …`) should bypass this proxy guard. Accessing `ns.foo` should return `undefined` (or whatever the underlying module naturally returns) rather than throwing a syntax error. In particular:

- `import * as ns from 'commonjs-pkg'` should allow reading arbitrary properties the CJS module may expose dynamically, without validation.
- `import * as ns from 'esm-pkg'` should behave consistently with how Node.js handles namespace exotic objects – properties that were not explicitly exported simply yield `undefined` at runtime.

The guard is useful for named/default imports to mimic Node’s top‑level static import checks, but it should be skipped entirely when the import is a wildcard namespace.

**Impact:**
Libraries and user code that rely on feature‑detection patterns, optional API surfaces, or dynamic properties on namespace imports break under Vite SSR. This is a regression compared to bundler‑less Node.js evaluation, making it impossible to migrate some libraries (e.g., modules that expose optional sub‑paths through a namespace) to Vite’s SSR without workarounds.

fix(ssr): skip esm proxy guard for namespace imports (#14988)


When using Vite's library build with a custom array of output options (`build.rollupOptions.output`), the build requires a global `build.lib.name` for any umd or iife output, even when every output entry already specifies its own `name`. This forces a redundant, sometimes inaccurate, configuration and prevents fine-grained per‑output naming.

## Steps to reproduce
1. Set up a library build with `build.lib.entry = 'src/index.js'`.
2. Omit `build.lib.name` entirely.
3. Provide an explicit output array via `build.rollupOptions.output`, for example:
   ```js
   output: [
     { format: 'umd', name: 'MyLibrary' },
     { format: 'es' }
   ]
   ```
4. Run `vite build`.

The build fails with:
> Option "build.lib.name" is required when output formats include "umd" or "iife".

## Expected behaviour
When the user supplies an explicit array of output options, Vite should **not** require a global `build.lib.name` for umd/iife entries. Instead, each output entry that uses the `'umd'` or `'iife'` format must include its own `name`. If such an entry is missing a name, the build should throw an error that points to the specific problematic entry (e.g. “Entries in \"build.rollupOptions.output\" must specify \"name\" when the format is \"umd\" or \"iife\".”).

If the user does **not** provide an explicit output array (i.e. relies on Vite’s default output generation or passes a single output object), then the existing requirement for a global `build.lib.name` remains correct (and is still validated only when umd or iife are among the selected formats).

## Impact
- Users are forced to duplicate information by setting both `build.lib.name` and per‑output `name`, leading to confusion and unnecessary configuration.
- Prevents legitimate use cases where different outputs genuinely need distinct names (even if uncommon, it should be possible).
- The current error message is misleading when the user has already supplied a name per output, making it unclear what needs to change to fix the build.

fix: throw missing name error only when 'umd' or 'iife' are used (#9886)


When using Vite’s dev server with SSR and HMR, updating a source file that is exclusively used by the server-rendered side (or exclusively by the client/browser side) of an isomorphic module sometimes does not trigger the expected HMR update. For example, after editing a file that feeds only the server-rendered content via an isomorphic virtual module, the server output remains stale and does not refresh. Conversely, editing a file that feeds only the client side may fail to update the browser content. This leads to a mismatch between the rendered result and the actual source code until a full page reload or server restart.

The underlying cause appears to be that the module graph does not distinguish between the sets of imported dependencies for the client and SSR contexts when the same module is consumed from both environments. As a result, HMR dependency tracking can lose the import information for one side, incorrectly prune modules, or miss necessary invalidations, leaving the affected environment unaware that its dependency has changed.

Expected behavior:
- The module graph should maintain separate tracking of imported modules for the client and SSR contexts, so that a module’s client-imported dependencies and SSR-imported dependencies are recognized independently.
- When a file that is only a dependency of one context (client or SSR) changes, HMR should invalidate and update only the relevant context, leaving the other unaffected.
- The server-rendered and client-hydrated output should always reflect the latest source after HMR, without requiring a full reload or restart.

Impact:
This bug severely hampers the developer experience when building applications that use isomorphic virtual modules or otherwise import different files under SSR and client. Developers are forced to manually reload or restart to see changes, breaking the fast feedback loop that Vite’s HMR is intended to provide.

fix: keep track of ssr version of imported modules separately (#11973)


### Bug: Relative imports with dots in filenames fail extension resolution

**Background**
When a relative import lacks a file extension (e.g., `import { bar } from './util/bar.util'`), Vite must resolve it to an existing file by trying known extensions (`.js`, `.ts`, `.jsx`, …) and directory indexes (`index.js`). The existing resolver logic incorrectly treats the last dot-separated segment of the path as a candidate extension, so a request for `./util/bar.util` does not try `./util/bar.util.js`; instead it may attempt `./util/bar.util` itself, fail, and break the build/dev server.

**Desired behavior**
When a relative import path has no explicit extension, resolution should:

1. Check whether the exact path (without extension) is an existing file.
2. If not, **append each supported extension** (`.mjs`, `.js`, `.ts`, `.jsx`, `.tsx`, `.json`) **to the whole path**, not just to the segment after the last dot.
3. Also **try `index` files** inside directories (e.g., `./util` → `./util/index.js`).
4. This must work for paths that contain dots in any position, including filenames like `bar.util`.

**Scope**
The fix should apply to the dev server’s import rewriting (`resolveImport` in `serverPluginModuleRewrite.ts`) and the underlying resolver (`resolver.ts`). The rewritten import should end up with the correct fully‑resolved path (e.g., `/@modules/…` for bare modules or a root‑relative path for project files).

**Acceptance criteria**
- Importing `./util/bar.util` (when `util/bar.util.js` exists) resolves without error.
- The same behavior holds for other supported extensions (`*.ts`, `*.tsx`, etc.) and for directory indexes.
- Existing resolution for normal bare‑module imports and `vue` special handling remains unchanged.
- No performance regression: avoid repeated `fs.stat` on every resolution; cache results where appropriate.

**Reference**
Issue #237 — Extension resolution fails for filenames containing dots.


## Vite dev server: surface no-cors block reason to browser console

When the dev server detects a cross-origin, no-cors request for a classic script (`sec-fetch-dest: script`), `rejectNoCorsRequestMiddleware` currently responds with HTTP 403 and a plaintext error body. Most browsers suppress the response body for 403s on script fetches, so developers only see a generic “Failed to load” error in the console — they never see the explanatory message about adding `crossorigin` to the `<script>` tag.

**Desired behavior**

For these blocked script requests **only** (i.e. when `sec-fetch-dest` is `script`, the request is not same-origin, and the mode is no-cors), the server should:

- respond with status **200** instead of 403,
- set `Content-Type: text/javascript`,
- and send a JavaScript snippet that immediately throws the existing error message, for example:

```js
throw new Error(
  '[Vite] Cross-origin requests for classic scripts must be made with CORS mode enabled.' +
    ' Make sure to set the "crossorigin" attribute on your <script> tag.',
);
```

The payload must not contain any real module code; it only includes the throw statement.

**Scope / invariants**

- The change applies **only** to the `sec-fetch-dest: script` code path in the middleware. Everything else (other destinations, same-origin requests, CORS requests) should continue unchanged — no spurious console errors from other resource types.
- The new JS response must not be emitted for non-script fetches, even if they also fail the origin check. Those should remain 403 (or whatever they currently return) and must not include the script error text.
- The error message content itself may stay the same as today’s text.
- The fix should not accidentally break existing Content-Security-Policy expectations — a simple `text/javascript` 200 response is safe.

**Motivation**

Debugging missing `crossorigin` attributes is a common friction point. By turning the block into a thrown error the browser will actually execute, the full message appears in the console, making the misconfiguration immediately obvious.
This mirrors a pattern used by other tools (e.g. webpack-dev-server) to surface security block reasons.

fix: improve `no-cors` request block error (#21902)


When using CSS modules with a custom `generateScopedName` option (e.g. `css.modules.generateScopedName`), the scoped class names generated during server-side rendering (SSR) can differ from the ones generated on the client. This mismatch causes hydration warnings, broken styles, or unstyled elements after hydration.

### Observed behaviour
- In a Vite project with CSS modules, the same `.module.css` file is transformed twice under different request IDs: once without a query string (used for SSR) and once with `?direct` (used for client-side hot module replacement / transforms).
- PostCSS receives the full ID, including the `?direct` suffix, when it processes the file. If a custom `generateScopedName` relies on the file path (for example to include a hash of the filename), the `?direct` suffix changes the input path seen by PostCSS, resulting in a different generated class name.
- The mismatch only appears when a custom `generateScopedName` is configured, but the root cause affects any PostCSS plugin or feature that interprets the file path.

### Expected behaviour
- The class names produced for a given `.module.css` file should be **identical** regardless of whether the request contains `?direct`. The `?direct` query is an internal Vite marker for client-side transforms and should not influence the PostCSS processing output.
- PostCSS should always receive a clean file path (without the `?direct` query) as the `from` / `to` option, so that downstream plugins and features see a consistent identity for the file.

### Impact
- Hydration mismatches in React, Vue, or other frameworks when CSS modules are consumed both on the server and client.
- Confusing and hard-to-debug issues that only surface when a non‑default `generateScopedName` is used, but conceptually affect any PostCSS-based transformation that is sensitive to the file identifier.

### Suggested fix
Strip the `?direct` query from the ID before passing it to PostCSS in the CSS compilation step. This ensures that `from` / `to` reflect the canonical file path and guarantees consistent output for server and client transforms.

fix(css): remove `?direct` in id for postcss process (#10514)


**Bug Report: Web Worker bundles ignore `build.sourcemap` configuration**

**Describe the bug**
When building a project that uses Web Workers (or Shared Workers), the main output bundles correctly generate sourcemaps according to the `build.sourcemap` option (`true`, `'inline'`, or `'hidden'`). However, the worker chunks emitted alongside them never receive any sourcemap at all. Debugging production worker code is impossible because the original sources cannot be reconstructed.

**Steps to reproduce**
1. Configure any `build.sourcemap` value (e.g., `true`, `'inline'`, or `'hidden'`).
2. Create a worker entry point that is loaded via `new Worker(new URL('./my-worker.js', import.meta.url))` or via the `?worker` import syntax.
3. Run `vite build`.
4. Inspect the output `dist` directory and the contents of the generated worker `.js` files.

**Expected behavior**
- Worker bundles should honor the `build.sourcemap` setting just like regular chunks.
- When `build.sourcemap` is `true`, a separate `.map` file should be emitted and a `//# sourceMappingURL=` comment should appear in the worker bundle pointing to it.
- When `build.sourcemap` is `'inline'`, the sourcemap should be inlined as a data URL comment at the end of the worker bundle.
- When `build.sourcemap` is `'hidden'`, the `.map` file should be emitted but no sourcemap comment should be present in the worker bundle.
- Inline workers (those imported with a `?inline` query) also need correct sourcemap linking. Because their final code is turned into a Blob URL, relative paths in the sourcemap comment will not resolve. For `sourcemap: true`, the comment must use the full asset path (relative to the configured `base`) so the debugger can locate the map. For `'hidden'`, no comment should be written, and for `'inline'`, the data URL should be inlined normally.
- All worker types (dedicated, shared, nested workers) must be covered.

**Actual behavior**
- No sourcemaps are generated for any worker bundles, regardless of the `build.sourcemap` setting.
- Worker `.js` files lack any `sourceMappingURL` comment, and no `.map` files are produced for them.
- Inline workers also lack sourcemaps entirely.

**Additional context**
- The main build pipeline uses Rollup under the hood, and the worker plugin currently calls Rollup’s `bundle.generate` with `sourcemap: true` (or based on config), but then discards the resulting sourcemap information and only uses the raw code.
- Special care is needed for inline workers because their execution environment (a `Blob` URL) has no knowledge of the asset directory layout, so relative sourcemap paths must be fully qualified.
- This feature is critical for debugging production worker code, especially in applications that rely heavily on offloading computation to workers.

feat(worker): Add sourcemap support for worker bundles (#5417)


Fix SSR transform so that a class declaration that extends an imported binding does not cause a runtime error.

Right now, when a class extends an imported identifier (e.g. `class A extends Foo` where `Foo` comes from `import { Foo } from '...'`), the SSR transform directly rewrites the superclass to the full imported member expression (`__vite_ssr_import_0__.Foo`). That expression cannot be evaluated before the import and breaks class declaration hoisting semantics. Instead, the transform must insert a local `const` declaration for the imported identifier at the module root (before the class) and use that local constant as the superclass.

Requirements:
- For every imported binding that appears as the superclass of a `ClassDeclaration`, emit `const <name> = <importBinding>;` exactly once per binding, placed after all import declarations and before the first class that references it.
- The same constant must be reused for all classes that extend the same imported binding.
- Exported classes (default or named) must still have the constant placed at the root, before any class declaration that uses the binding.
- Identifiers used as superclass must never be emitted as a raw member expression on an import object; a local constant must be used instead.
- The `parentStack` provided to identifier visitors must not contain `ImportDeclaration` nodes, so that surrounding scope detection for superclass rewrites works correctly without influence from import statements.

fix(ssr): handle imported binding being used as super class


## Bug Report: TypeScript imports of `.tsx` modules using `.js`/`.jsx` extensions fail to resolve

### Observed Behavior
When a TypeScript module imports another module using a JavaScript output extension (`.js`, `.jsx`, `.mjs`, `.cjs`), Vite’s resolver only replaces the extension with `.ts`. It does **not** attempt to resolve the corresponding `.tsx` file. This causes module-not-found errors when the target file is a `.tsx` module that only exists with a `.tsx` extension.

For example:

- `import { msg } from './hellotsx.js'` from a `.ts` file fails if the only real file is `hellotsx.tsx`.
- `import { msg } from './hellojsx.jsx'` from a `.ts` file fails if the only real file is `hellojsx.tsx`.
- `import { msg } from './other.mjs'` fails if only `other.mtsx` (or `other.mts`) exists.

### Expected Behavior
When a request is detected as coming from a TypeScript importer (`isFromTsImporter` is set) and the import path ends with a known TypeScript output extension (`.js`, `.jsx`, `.mjs`, `.cjs`), the resolver should:

1. Replace the extension with `.ts` and attempt to resolve.
2. If that fails, attempt the `.tsx` extension for the appropriate base.
3. For `.jsx` imports, only `.tsx` should be attempted (not `.ts`).
4. For `.mjs` imports, both `.mts` and `.mtsx` should be attempted.
5. For `.cjs` imports, both `.cts` and `.ctsx` should be attempted.
6. Any query string present in the original import path must be preserved in the generated candidate paths.

The same logic should apply for file paths that contain `.js` before the final extension (e.g., `./foo.js.js` → `./foo.js.tsx` should be checked).

### Impact
This issue prevents seamless interop between plain TypeScript (`.ts`) files and TSX (`.tsx`) files, which is a common pattern in projects using JSX/TSX. It forces developers to use the `.tsx` extension explicitly in imports, which diverges from TypeScript’s language-level behavior where `.tsx` files are reachable via `.js` import specifiers. The missing resolution also affects `.mjs`/`.cjs` interop with `.mtsx`/`.ctsx` modules.

### Additional Context
- The existing behaviour is provided by `getTsSrcPath()`, which performs a single extension replacement (e.g., `.js` → `.ts`). It does not consider `.tsx` alternatives or special rules for `.jsx`/`.mjs`/`.cjs`.
- The resolver code path in `tryResolveFile()` can be extended to iterate over a list of candidate source paths instead of a single candidate, aborting on the first successful resolve.
- The fix must respect the original import’s query parameters.

fix(resolve): try .tsx extension for .js import from typescript module (#7005)