diff --git a/.changeset/twelve-paws-remember.md b/.changeset/twelve-paws-remember.md new file mode 100644 index 000000000000..1d484047af0c --- /dev/null +++ b/.changeset/twelve-paws-remember.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': major +--- + +breaking: fix path resolution diff --git a/packages/kit/src/core/postbuild/fixtures/base/output.json b/packages/kit/src/core/postbuild/fixtures/base/output.json index af7a9e70a93c..203973f65687 100644 --- a/packages/kit/src/core/postbuild/fixtures/base/output.json +++ b/packages/kit/src/core/postbuild/fixtures/base/output.json @@ -2,7 +2,7 @@ "hrefs": [ "/base-path/styles.css", "/base-path/favicon.png", - "https://external.com", + "https://external.com/", "/base-path/wheee", "/base-path/wheee2", "/base-path/wheee3", diff --git a/packages/kit/src/core/postbuild/fixtures/basic-href/output.json b/packages/kit/src/core/postbuild/fixtures/basic-href/output.json index 415f7b38671f..48b9db674814 100644 --- a/packages/kit/src/core/postbuild/fixtures/basic-href/output.json +++ b/packages/kit/src/core/postbuild/fixtures/basic-href/output.json @@ -2,7 +2,7 @@ "hrefs": [ "/styles.css", "/favicon.png", - "https://external.com", + "https://external.com/", "/wheee", "/wheee2", "/wheee3", diff --git a/packages/kit/src/core/postbuild/fixtures/href-with-character-reference/output.json b/packages/kit/src/core/postbuild/fixtures/href-with-character-reference/output.json index eb649d122431..0ac291842779 100644 --- a/packages/kit/src/core/postbuild/fixtures/href-with-character-reference/output.json +++ b/packages/kit/src/core/postbuild/fixtures/href-with-character-reference/output.json @@ -3,9 +3,9 @@ "/styles.css", "/favicon.png", "/test&ersand", - "/test\"quotation", - "/test♡decimal", - "/test♥hex" + "/test%22quotation", + "/test%E2%99%A1decimal", + "/test%E2%99%A5hex" ], "ids": [] } diff --git a/packages/kit/src/core/postbuild/fixtures/ids/output.json b/packages/kit/src/core/postbuild/fixtures/ids/output.json index e749d3128d7e..750406f0dbcc 100644 --- a/packages/kit/src/core/postbuild/fixtures/ids/output.json +++ b/packages/kit/src/core/postbuild/fixtures/ids/output.json @@ -1,4 +1,4 @@ { - "hrefs": ["/#encöded"], + "hrefs": ["/#enc%C3%B6ded"], "ids": ["before", "after", "encöded"] } diff --git a/packages/kit/src/core/postbuild/fixtures/include-rel-external/output.json b/packages/kit/src/core/postbuild/fixtures/include-rel-external/output.json index 1d2f9337af06..b389f1b5a3e7 100644 --- a/packages/kit/src/core/postbuild/fixtures/include-rel-external/output.json +++ b/packages/kit/src/core/postbuild/fixtures/include-rel-external/output.json @@ -1,4 +1,4 @@ { - "hrefs": ["/styles.css", "/favicon.png", "https://external.com"], + "hrefs": ["/styles.css", "/favicon.png", "https://external.com/"], "ids": [] } diff --git a/packages/kit/src/core/postbuild/fixtures/meta/output.json b/packages/kit/src/core/postbuild/fixtures/meta/output.json index 76cfe72ada91..2e5881e7521d 100644 --- a/packages/kit/src/core/postbuild/fixtures/meta/output.json +++ b/packages/kit/src/core/postbuild/fixtures/meta/output.json @@ -1,4 +1,9 @@ { - "hrefs": ["https://external.com", "/og-image.jpg", "https://example.com/audio.mp3", "/video.mp4"], + "hrefs": [ + "https://external.com/", + "/og-image.jpg", + "https://example.com/audio.mp3", + "/video.mp4" + ], "ids": [] } diff --git a/packages/kit/src/core/postbuild/fixtures/unquoted-attributes/output.json b/packages/kit/src/core/postbuild/fixtures/unquoted-attributes/output.json index 2f95abb62dd4..d2d68c5d41e0 100644 --- a/packages/kit/src/core/postbuild/fixtures/unquoted-attributes/output.json +++ b/packages/kit/src/core/postbuild/fixtures/unquoted-attributes/output.json @@ -1,4 +1,4 @@ { - "hrefs": ["/styles.css", "/favicon.png", "https://external.com", "/wheee"], + "hrefs": ["/styles.css", "/favicon.png", "https://external.com/", "/wheee"], "ids": [] } diff --git a/packages/kit/src/utils/url.js b/packages/kit/src/utils/url.js index ac6e25581e52..ebcd3702ea86 100644 --- a/packages/kit/src/utils/url.js +++ b/packages/kit/src/utils/url.js @@ -6,39 +6,20 @@ import { BROWSER } from 'esm-env'; */ export const SCHEME = /^[a-z][a-z\d+\-.]+:/i; -const absolute = /^([a-z]+:)?\/?\//; +const internal = new URL('sveltekit-internal://'); /** * @param {string} base * @param {string} path */ export function resolve(base, path) { - if (SCHEME.test(path)) return path; - if (path[0] === '#') return base + path; - if (path === '') return base; + // special case + if (path[0] === '/' && path[1] === '/') return path; - const base_match = absolute.exec(base); - const path_match = absolute.exec(path); + let url = new URL(base, internal); + url = new URL(path, url); - if (!base_match) { - throw new Error(`bad base path: "${base}"`); - } - - const baseparts = path_match ? [] : base.slice(base_match[0].length).split('/'); - const pathparts = path_match ? path.slice(path_match[0].length).split('/') : path.split('/'); - - baseparts.pop(); - - for (let i = 0; i < pathparts.length; i += 1) { - const part = pathparts[i]; - if (part === '.') continue; - else if (part === '..') baseparts.pop(); - else baseparts.push(part); - } - - const prefix = (path_match && path_match[0]) || (base_match && base_match[0]) || ''; - - return `${prefix}${baseparts.join('/')}`; + return url.protocol === internal.protocol ? url.pathname + url.search + url.hash : url.href; } /** @param {string} path */ diff --git a/packages/kit/src/utils/url.spec.js b/packages/kit/src/utils/url.spec.js index 8f37b5330def..7de41b1e04d1 100644 --- a/packages/kit/src/utils/url.spec.js +++ b/packages/kit/src/utils/url.spec.js @@ -61,6 +61,10 @@ describe('resolve', (test) => { test('resolves empty string', () => { assert.equal(resolve('/a/b/c', ''), '/a/b/c'); }); + + test('resolves .', () => { + assert.equal(resolve('/a/b/c', '.'), '/a/b/'); + }); }); describe('normalize_path', (test) => { diff --git a/packages/kit/test/apps/basics/src/routes/cookies/encoding/set/+server.js b/packages/kit/test/apps/basics/src/routes/cookies/encoding/set/+server.js index 6198238b21ea..141392352327 100644 --- a/packages/kit/test/apps/basics/src/routes/cookies/encoding/set/+server.js +++ b/packages/kit/test/apps/basics/src/routes/cookies/encoding/set/+server.js @@ -3,6 +3,6 @@ import { redirect } from '@sveltejs/kit'; /** @type {import('@sveltejs/kit').RequestHandler} */ export const GET = (event) => { const needsEncoding = 'teapot, jane austen'; - event.cookies.set('encoding', needsEncoding, { path: '.' }); + event.cookies.set('encoding', needsEncoding, { path: '/cookies/encoding' }); redirect(303, '/cookies/encoding'); };