diff --git a/src/scripts/settings/webSettings.js b/src/scripts/settings/webSettings.js index 2ffe290d88..80587713bf 100644 --- a/src/scripts/settings/webSettings.js +++ b/src/scripts/settings/webSettings.js @@ -1,9 +1,48 @@ let data; +const urlResolver = document.createElement('a'); + +// `fetch` with `file:` support +// Recent browsers seem to support `file` protocol under some conditions. +// Based on https://github.com/github/fetch/pull/92#issuecomment-174730593 +// https://github.com/github/fetch/pull/92#issuecomment-512187452 +async function fetchLocal(url, options) { + urlResolver.href = url; + + const requestURL = urlResolver.href; + + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest; + + xhr.onload = () => { + // `file` protocol has invalid OK status + let status = xhr.status; + if (requestURL.startsWith('file:') && status === 0) { + status = 200; + } + + /* eslint-disable-next-line compat/compat */ + resolve(new Response(xhr.responseText, {status: status})); + }; + + xhr.onerror = () => { + reject(new TypeError('Local request failed')); + }; + + xhr.open('GET', url); + + if (options && options.cache) { + xhr.setRequestHeader('Cache-Control', options.cache); + } + + xhr.send(null); + }); +} + async function getConfig() { if (data) return Promise.resolve(data); try { - const response = await fetch('config.json', { + const response = await fetchLocal('config.json', { cache: 'no-cache' }); @@ -22,7 +61,7 @@ async function getConfig() { async function getDefaultConfig() { try { - const response = await fetch('config.template.json', { + const response = await fetchLocal('config.template.json', { cache: 'no-cache' });