]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix: preserve extra properties when resolving locations
authorEduardo San Martin Morote <posva13@gmail.com>
Fri, 10 Oct 2025 10:13:00 +0000 (12:13 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Fri, 10 Oct 2025 10:13:00 +0000 (12:13 +0200)
packages/router/src/experimental/route-resolver/resolver-fixed.spec.ts
packages/router/src/experimental/route-resolver/resolver-fixed.ts

index 7d8249de48b5ab67c661437d31e7b6bf3cda348c..196f44a3f562412bb946fcdbf50d21914866097c 100644 (file)
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest'
 import { createFixedResolver } from './resolver-fixed'
-import { NO_MATCH_LOCATION } from './resolver-abstract'
+import { MatcherLocationRaw, NO_MATCH_LOCATION } from './resolver-abstract'
 import {
   EmptyParams,
   MatcherPatternHash,
@@ -266,6 +266,37 @@ describe('fixed resolver', () => {
         })
       })
 
+      it('keeps extra properties like state and replace from target location', () => {
+        const resolver = createFixedResolver([
+          { name: 'any-path', path: ANY_PATH_PATTERN_MATCHER },
+        ])
+
+        const currentLocation = resolver.resolve({ path: '/bar' })
+
+        // extra parameters that should be preserved
+        const extra = { state: { a: 1 }, replace: true }
+
+        for (const path of ['foo', './foo', '../foo']) {
+          expect(
+            resolver.resolve(
+              {
+                // done this way because TS accepts this kind of combination
+                path,
+                ...extra,
+              },
+              currentLocation
+            )
+          ).toMatchObject({
+            params: {},
+            path: '/foo',
+            query: {},
+            hash: {},
+            state: { a: 1 },
+            replace: true,
+          })
+        }
+      })
+
       it('resolves relative object locations', () => {
         const resolver = createFixedResolver([
           { name: 'any-path', path: ANY_PATH_PATTERN_MATCHER },
@@ -445,6 +476,30 @@ describe('fixed resolver', () => {
           params: { pathMatch: '/?a=a&b=b#h' },
         })
       })
+
+      it('keeps extra properties like state and replace from target location', () => {
+        const resolver = createFixedResolver([
+          { name: 'any-path', path: ANY_PATH_PATTERN_MATCHER },
+        ])
+
+        // extra parameters that should be preserved
+        const extra = { state: { a: 1 }, replace: true }
+
+        expect(
+          resolver.resolve({
+            // done this way because TS accepts this kind of combination
+            path: '/foo',
+            ...extra,
+          })
+        ).toMatchObject({
+          params: {},
+          path: '/foo',
+          query: {},
+          hash: {},
+          state: { a: 1 },
+          replace: true,
+        })
+      })
     })
 
     describe('named locations', () => {
@@ -490,6 +545,32 @@ describe('fixed resolver', () => {
         ).toThrowError('Record "nonexistent" not found')
       })
 
+      it('keeps extra properties like state and replace from target location', () => {
+        const resolver = createFixedResolver([
+          { name: 'home', path: EMPTY_PATH_PATTERN_MATCHER },
+        ])
+
+        // extra parameters that should be preserved
+        const extra = { state: { a: 1 }, replace: true }
+
+        expect(
+          resolver.resolve({
+            // done this way because TS accepts this kind of combination
+            name: 'home',
+            params: {},
+            ...extra,
+          })
+        ).toMatchObject({
+          name: 'home',
+          params: {},
+          path: '/',
+          query: {},
+          hash: {},
+          state: { a: 1 },
+          replace: true,
+        })
+      })
+
       it('resolves named locations with explicit query', () => {
         const resolver = createFixedResolver([
           {
index 145298acbb217e5831e38b5c8a4705af37240d73..70b91609871ce87aa114fddb9ed5a4ecee4f3b19 100644 (file)
@@ -204,6 +204,8 @@ export function createFixedResolver<
         // @ts-expect-error: to is never
         const path = to.path ?? '/'
         return {
+          // type is never
+          ...(to as any),
           ...NO_MATCH_LOCATION,
           fullPath: NEW_stringifyURL(stringifyQuery, path, query, hash),
           path,
@@ -248,6 +250,8 @@ export function createFixedResolver<
       )
 
       const url: LocationNormalized = {
+        // preserve other fields like `state` and `replace`
+        ...to,
         fullPath: NEW_stringifyURL(
           stringifyQuery,
           path,
@@ -279,6 +283,8 @@ export function createFixedResolver<
         const query = normalizeQuery(to.query)
         const path = resolveRelativePath(to.path, currentLocation?.path || '/')
         url = {
+          // preserve other fields like `state` and `replace`
+          ...to,
           fullPath: NEW_stringifyURL(stringifyQuery, path, query, to.hash),
           path,
           query,