From b3868e537371e9118fdbe3aacb5eb6cb833c39c5 Mon Sep 17 00:00:00 2001 From: AlexandrHoroshih Date: Thu, 30 Jan 2025 20:27:46 +0700 Subject: [PATCH 1/3] Add fallback validation for Safari 14.0 --- packages/core/src/fetch/__tests__/lib.test.ts | 20 +++++++++- packages/core/src/fetch/lib.ts | 37 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/core/src/fetch/__tests__/lib.test.ts b/packages/core/src/fetch/__tests__/lib.test.ts index 847dd7bc5..972bacadf 100644 --- a/packages/core/src/fetch/__tests__/lib.test.ts +++ b/packages/core/src/fetch/__tests__/lib.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'vitest'; -import { mergeRecords } from '../lib'; +import { mergeRecords, splitUrl } from '../lib'; describe('mergeRecords', () => { test('empty to empty object', () => { @@ -41,3 +41,21 @@ describe('mergeRecords', () => { }); }); }); + +describe('Safari 14.0 bug', () => { + test('splitUrl', () => { + const url = 'https://example.com/api?foo=bar'; + + const split = splitUrl(url); + + expect(split).toEqual({ + base: 'https://example.com', + path: '/api?foo=bar', + }); + + const url1 = new URL(url); + const url2 = new URL(split.path, split.base); + + expect(url1.href).toBe(url2.href); + }); +}); diff --git a/packages/core/src/fetch/lib.ts b/packages/core/src/fetch/lib.ts index f2c5a9b56..3f1558597 100644 --- a/packages/core/src/fetch/lib.ts +++ b/packages/core/src/fetch/lib.ts @@ -96,6 +96,27 @@ export function formatUrl( try { return new URL(urlString, urlBase); } catch (e) { + if (!urlBase) { + try { + /** + * Fallback branch for Safari 14.0 + * @see https://github.com/igorkamyshev/farfetched/issues/528 + * + * If url is full path, but we're in Safari 14.0, we will have a TypeError for new URL(urlString, undefined) + * + * So we have to manually split url into base and path parts first + */ + const { base, path } = splitUrl(urlString); + + return new URL(path, base); + } catch (_e) { + throw configurationError({ + reason: 'Invalid URL', + validationErrors: [`"${urlString}" is not valid URL`], + }); + } + } + throw configurationError({ reason: 'Invalid URL', validationErrors: [`"${urlString}" is not valid URL`], @@ -129,3 +150,19 @@ function clearValue( return value ?? null; } + +/** + * @see https://github.com/igorkamyshev/farfetched/issues/528 + */ +export function splitUrl(urlString: string): { base: string; path: string } { + const urlPattern = /^(https?:\/\/[^\/]+)(\/.*)?$/; + const match = urlString.match(urlPattern); + + if (!match) { + throw new Error(`Invalid URL: ${urlString}`); + } + + const base = match[1]; + const path = match[2] || ''; + return { base, path }; +} From 7fc6e28788ed94c1ada5d6c3d7419ce5783db4a3 Mon Sep 17 00:00:00 2001 From: AlexandrHoroshih Date: Thu, 30 Jan 2025 20:30:14 +0700 Subject: [PATCH 2/3] Add workaround for Safari 14.0 bugged implementation of URL constructor --- .changeset/heavy-otters-hang.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/heavy-otters-hang.md diff --git a/.changeset/heavy-otters-hang.md b/.changeset/heavy-otters-hang.md new file mode 100644 index 000000000..701d0c36f --- /dev/null +++ b/.changeset/heavy-otters-hang.md @@ -0,0 +1,5 @@ +--- +"@farfetched/core": patch +--- + +Add workaround for Safari 14.0 bugged implementation of URL constructor From 5a28d32002ac9c2b469e19834fc56c8a083ac367 Mon Sep 17 00:00:00 2001 From: AlexandrHoroshih Date: Thu, 30 Jan 2025 20:37:33 +0700 Subject: [PATCH 3/3] Add better workaraound --- packages/core/src/fetch/__tests__/lib.test.ts | 20 +-------- packages/core/src/fetch/lib.ts | 45 +++---------------- 2 files changed, 8 insertions(+), 57 deletions(-) diff --git a/packages/core/src/fetch/__tests__/lib.test.ts b/packages/core/src/fetch/__tests__/lib.test.ts index 972bacadf..847dd7bc5 100644 --- a/packages/core/src/fetch/__tests__/lib.test.ts +++ b/packages/core/src/fetch/__tests__/lib.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'vitest'; -import { mergeRecords, splitUrl } from '../lib'; +import { mergeRecords } from '../lib'; describe('mergeRecords', () => { test('empty to empty object', () => { @@ -41,21 +41,3 @@ describe('mergeRecords', () => { }); }); }); - -describe('Safari 14.0 bug', () => { - test('splitUrl', () => { - const url = 'https://example.com/api?foo=bar'; - - const split = splitUrl(url); - - expect(split).toEqual({ - base: 'https://example.com', - path: '/api?foo=bar', - }); - - const url1 = new URL(url); - const url2 = new URL(split.path, split.base); - - expect(url1.href).toBe(url2.href); - }); -}); diff --git a/packages/core/src/fetch/lib.ts b/packages/core/src/fetch/lib.ts index 3f1558597..2ead30d12 100644 --- a/packages/core/src/fetch/lib.ts +++ b/packages/core/src/fetch/lib.ts @@ -93,30 +93,15 @@ export function formatUrl( urlString = `${url}?${queryString}`; } + /** + * Workararound for Safari 14.0 + * @see https://github.com/igorkamyshev/farfetched/issues/528 + */ + const urlArgs = [urlString, urlBase].filter(Boolean) as [string, string]; + try { - return new URL(urlString, urlBase); + return new URL(...urlArgs); } catch (e) { - if (!urlBase) { - try { - /** - * Fallback branch for Safari 14.0 - * @see https://github.com/igorkamyshev/farfetched/issues/528 - * - * If url is full path, but we're in Safari 14.0, we will have a TypeError for new URL(urlString, undefined) - * - * So we have to manually split url into base and path parts first - */ - const { base, path } = splitUrl(urlString); - - return new URL(path, base); - } catch (_e) { - throw configurationError({ - reason: 'Invalid URL', - validationErrors: [`"${urlString}" is not valid URL`], - }); - } - } - throw configurationError({ reason: 'Invalid URL', validationErrors: [`"${urlString}" is not valid URL`], @@ -150,19 +135,3 @@ function clearValue( return value ?? null; } - -/** - * @see https://github.com/igorkamyshev/farfetched/issues/528 - */ -export function splitUrl(urlString: string): { base: string; path: string } { - const urlPattern = /^(https?:\/\/[^\/]+)(\/.*)?$/; - const match = urlString.match(urlPattern); - - if (!match) { - throw new Error(`Invalid URL: ${urlString}`); - } - - const base = match[1]; - const path = match[2] || ''; - return { base, path }; -}