You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
4.5 KiB

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSymbolicateMiddleware = void 0;
const metro_config_1 = require("@expo/metro-config");
const path_1 = __importDefault(require("path"));
const Symbolicator_1 = require("./Symbolicator");
const getFileAsync_1 = require("./getFileAsync");
// Customize the stack frames like we do in Metro projects.
function customizeFrame(frame) {
var _a;
let collapse = Boolean(frame.file && metro_config_1.INTERNAL_CALLSITES_REGEX.test(frame.file));
if (!collapse) {
// This represents the first frame of the stacktrace.
// Often this looks like: `__r(0);`.
// The URL will also be unactionable in the app and therefore not very useful to the developer.
if (frame.column === 3 &&
frame.methodName === 'global code' &&
((_a = frame.file) === null || _a === void 0 ? void 0 : _a.match(/^https?:\/\//g))) {
collapse = true;
}
}
return { ...(frame || {}), collapse };
}
function createSymbolicateMiddleware({ projectRoot, logger, compiler, }) {
const getFilenameFromUrl = (0, getFileAsync_1.createGetFileNameFromUrl)(compiler);
const symbolicate = new Symbolicator_1.Symbolicator({
projectRoot,
logger,
customizeFrame,
async getFileAsync(props) {
const fileName = getFilenameFromUrl(props);
return (0, getFileAsync_1.getFileFromCompilerAsync)(compiler, { fileName, platform: props.platform });
},
async getSourceMapAsync(props) {
var _a, _b;
const fileName = getFilenameFromUrl(props);
const fallbackSourceMapFilename = `${fileName}.map`;
const bundle = await (0, getFileAsync_1.getFileFromCompilerAsync)(compiler, {
fileName,
platform: props.platform,
});
const sourceMappingUrl = (_a = /sourceMappingURL=(.+)$/.exec(bundle)) === null || _a === void 0 ? void 0 : _a[1];
const sourceMapBasename = (_b = sourceMappingUrl === null || sourceMappingUrl === void 0 ? void 0 : sourceMappingUrl.split('?')) === null || _b === void 0 ? void 0 : _b[0];
let sourceMapFilename = fallbackSourceMapFilename;
if (sourceMapBasename) {
sourceMapFilename = path_1.default.join(path_1.default.dirname(fileName), sourceMapBasename);
}
let parseError = null;
for (const file of [sourceMapFilename, fallbackSourceMapFilename]) {
try {
return await (0, getFileAsync_1.getFileFromCompilerAsync)(compiler, {
fileName: file,
platform: props.platform,
});
}
catch (error) {
parseError = error;
console.warn('Failed to read source map from sourceMappingURL:', file);
// logger.warn({ tag: 'dev-server' }, 'Failed to read source map from sourceMappingURL');
}
}
throw parseError;
},
});
return async function (req, res) {
var _a, _b;
try {
if (!req.rawBody) {
return res.writeHead(400).end('Missing request rawBody.');
}
const { stack } = JSON.parse(req.rawBody);
const platform = (_b = (_a = (0, getFileAsync_1.getPlatformFromRequest)(req)) !== null && _a !== void 0 ? _a : Symbolicator_1.Symbolicator.inferPlatformFromStack(stack)) !== null && _b !== void 0 ? _b : 'web';
if (!platform) {
return res
.writeHead(400)
.end('Missing expo-platform header, platform query parameter, or platform parameter in source map comment url');
}
const parsed = await symbolicate.process(stack, { platform });
return res.end(JSON.stringify(parsed));
}
catch (error) {
console.error(`Failed to symbolicate: ${error} ${error.stack}`);
// logger.error({ tag: 'dev-server' }, `Failed to symbolicate: ${error} ${error.stack}`);
res.statusCode = 500;
return res.end(JSON.stringify({ error: error.message }));
}
};
}
exports.createSymbolicateMiddleware = createSymbolicateMiddleware;
//# sourceMappingURL=symbolicateMiddleware.js.map