forked from mirrors/gecko-dev
This used to be a node package. Let's make it become regular commonjs devtools modules. This will make it trivial to migrate this to ES Modules. Also possibly make this code become the unique layer in m-c on top of the source-map package. We no longer use webpack to build the two bundles (index.js and worker.js), instead, we are using the toolkit worker loader (require.js) in order to load all this code without any build step. As this is no longer a node package, I removed node-specific modules (assertRoot/wasmAsset) and simplify the definition of wasm file URIs as they are now fixed. Also moving the debugger to load internal "devtools/client/shared/source-map/source-map.js" module in jest as running the Web Worker instantiated by source-map/index.js is too complex. Differential Revision: https://phabricator.services.mozilla.com/D159115
134 lines
4.1 KiB
JavaScript
134 lines
4.1 KiB
JavaScript
/* 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 {
|
|
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");
|
|
const {
|
|
createConsumer,
|
|
} = require("resource://devtools/client/shared/source-map-loader/utils/createConsumer");
|
|
|
|
// 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,
|
|
sourceMapBaseURL: generatedSource.sourceMapBaseURL,
|
|
});
|
|
|
|
if (fetched.isDwarf) {
|
|
fetched = { content: await convertToJSON(fetched.content) };
|
|
}
|
|
|
|
// Create the source map and fix it up.
|
|
let map = await createConsumer(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 };
|