diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/shared/source-map-loader/utils/fetchSourceMap.js | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/shared/source-map-loader/utils/fetchSourceMap.js')
-rw-r--r-- | devtools/client/shared/source-map-loader/utils/fetchSourceMap.js | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/devtools/client/shared/source-map-loader/utils/fetchSourceMap.js b/devtools/client/shared/source-map-loader/utils/fetchSourceMap.js new file mode 100644 index 0000000000..8cf7ab31a9 --- /dev/null +++ b/devtools/client/shared/source-map-loader/utils/fetchSourceMap.js @@ -0,0 +1,137 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ + +"use strict"; + +const { + networkRequest, +} = require("resource://devtools/client/shared/source-map-loader/utils/network-request"); + +const { + SourceMapConsumer, +} = require("resource://devtools/client/shared/vendor/source-map/source-map.js"); +const { + getSourceMap, + setSourceMap, +} = require("resource://devtools/client/shared/source-map-loader/utils/sourceMapRequests"); +const { + WasmRemap, +} = require("resource://devtools/client/shared/source-map-loader/utils/wasmRemap"); +const { + convertToJSON, +} = require("resource://devtools/client/shared/source-map-loader/wasm-dwarf/convertToJSON"); + +// URLs which have been seen in a completed source map request. +const originalURLs = new Set(); + +function clearOriginalURLs() { + originalURLs.clear(); +} + +function hasOriginalURL(url) { + return originalURLs.has(url); +} + +function _resolveSourceMapURL(source) { + let { sourceMapBaseURL, sourceMapURL } = source; + sourceMapBaseURL = sourceMapBaseURL || ""; + sourceMapURL = sourceMapURL || ""; + + if (!sourceMapBaseURL) { + // If the source doesn't have a URL, don't resolve anything. + return { sourceMapURL, baseURL: sourceMapURL }; + } + + let resolvedString; + let baseURL; + + // When the sourceMap is a data: URL, fall back to using the source's URL, + // if possible. We don't use `new URL` here because it will be _very_ slow + // for large inlined source-maps, and we don't actually need to parse them. + if (sourceMapURL.startsWith("data:")) { + resolvedString = sourceMapURL; + baseURL = sourceMapBaseURL; + } else { + resolvedString = new URL( + sourceMapURL, + // If the URL is a data: URL, the sourceMapURL needs to be absolute, so + // we might as well pass `undefined` to avoid parsing a potentially + // very large data: URL for no reason. + sourceMapBaseURL.startsWith("data:") ? undefined : sourceMapBaseURL + ).toString(); + baseURL = resolvedString; + } + + return { sourceMapURL: resolvedString, baseURL }; +} + +async function _resolveAndFetch(generatedSource) { + // Fetch the sourcemap over the network and create it. + const { sourceMapURL, baseURL } = _resolveSourceMapURL(generatedSource); + + let fetched = await networkRequest(sourceMapURL, { + loadFromCache: false, + // Blocking redirects on the sourceMappingUrl as its not easy to verify if the + // redirect protocol matches the supported ones. + allowRedirects: false, + sourceMapBaseURL: generatedSource.sourceMapBaseURL, + }); + + if (fetched.isDwarf) { + fetched = { content: await convertToJSON(fetched.content) }; + } + + // Create the source map and fix it up. + let map = await new SourceMapConsumer(fetched.content, baseURL); + + if (generatedSource.isWasm) { + map = new WasmRemap(map); + // Check if experimental scope info exists. + if (fetched.content.includes("x-scopes")) { + const parsedJSON = JSON.parse(fetched.content); + map.xScopes = parsedJSON["x-scopes"]; + } + } + + // Extend the default map object with sourceMapBaseURL, used to check further + // network requests made for this sourcemap. + map.sourceMapBaseURL = generatedSource.sourceMapBaseURL; + + if (map && map.sources) { + map.sources.forEach(url => originalURLs.add(url)); + } + + return map; +} + +function fetchSourceMap(generatedSource) { + const existingRequest = getSourceMap(generatedSource.id); + + // If it has already been requested, return the request. Make sure + // to do this even if sourcemapping is turned off, because + // pretty-printing uses sourcemaps. + // + // An important behavior here is that if it's in the middle of + // requesting it, all subsequent calls will block on the initial + // request. + if (existingRequest) { + return existingRequest; + } + + if (!generatedSource.sourceMapURL) { + return null; + } + + // Fire off the request, set it in the cache, and return it. + const req = _resolveAndFetch(generatedSource); + // Make sure the cached promise does not reject, because we only + // want to report the error once. + setSourceMap( + generatedSource.id, + req.catch(() => null) + ); + return req; +} + +module.exports = { fetchSourceMap, hasOriginalURL, clearOriginalURLs }; |