[6a3a178] | 1 | "use strict";
|
---|
| 2 |
|
---|
| 3 | Object.defineProperty(exports, "__esModule", {
|
---|
| 4 | value: true
|
---|
| 5 | });
|
---|
| 6 | exports.getSourceMappingURL = getSourceMappingURL;
|
---|
| 7 | exports.fetchFromURL = fetchFromURL;
|
---|
| 8 | exports.flattenSourceMap = flattenSourceMap;
|
---|
| 9 |
|
---|
| 10 | var _path = _interopRequireDefault(require("path"));
|
---|
| 11 |
|
---|
| 12 | var _url = _interopRequireDefault(require("url"));
|
---|
| 13 |
|
---|
| 14 | var _sourceMapJs = _interopRequireDefault(require("source-map-js"));
|
---|
| 15 |
|
---|
| 16 | var _iconvLite = require("iconv-lite");
|
---|
| 17 |
|
---|
| 18 | var _parseDataUrl = _interopRequireDefault(require("./parse-data-url"));
|
---|
| 19 |
|
---|
| 20 | var _labelsToNames = _interopRequireDefault(require("./labels-to-names"));
|
---|
| 21 |
|
---|
| 22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
---|
| 23 |
|
---|
| 24 | // Matches only the last occurrence of sourceMappingURL
|
---|
| 25 | const innerRegex = /\s*[#@]\s*sourceMappingURL\s*=\s*([^\s'"]*)\s*/;
|
---|
| 26 | /* eslint-disable prefer-template */
|
---|
| 27 |
|
---|
| 28 | const sourceMappingURLRegex = RegExp("(?:" + "/\\*" + "(?:\\s*\r?\n(?://)?)?" + "(?:" + innerRegex.source + ")" + "\\s*" + "\\*/" + "|" + "//(?:" + innerRegex.source + ")" + ")" + "\\s*");
|
---|
| 29 | /* eslint-enable prefer-template */
|
---|
| 30 |
|
---|
| 31 | function labelToName(label) {
|
---|
| 32 | const labelLowercase = String(label).trim().toLowerCase();
|
---|
| 33 | return _labelsToNames.default[labelLowercase] || null;
|
---|
| 34 | }
|
---|
| 35 |
|
---|
| 36 | async function flattenSourceMap(map) {
|
---|
| 37 | const consumer = await new _sourceMapJs.default.SourceMapConsumer(map);
|
---|
| 38 | const generatedMap = map.file ? new _sourceMapJs.default.SourceMapGenerator({
|
---|
| 39 | file: map.file
|
---|
| 40 | }) : new _sourceMapJs.default.SourceMapGenerator();
|
---|
| 41 | consumer.sources.forEach(sourceFile => {
|
---|
| 42 | const sourceContent = consumer.sourceContentFor(sourceFile, true);
|
---|
| 43 | generatedMap.setSourceContent(sourceFile, sourceContent);
|
---|
| 44 | });
|
---|
| 45 | consumer.eachMapping(mapping => {
|
---|
| 46 | const {
|
---|
| 47 | source
|
---|
| 48 | } = consumer.originalPositionFor({
|
---|
| 49 | line: mapping.generatedLine,
|
---|
| 50 | column: mapping.generatedColumn
|
---|
| 51 | });
|
---|
| 52 | const mappings = {
|
---|
| 53 | source,
|
---|
| 54 | original: {
|
---|
| 55 | line: mapping.originalLine,
|
---|
| 56 | column: mapping.originalColumn
|
---|
| 57 | },
|
---|
| 58 | generated: {
|
---|
| 59 | line: mapping.generatedLine,
|
---|
| 60 | column: mapping.generatedColumn
|
---|
| 61 | }
|
---|
| 62 | };
|
---|
| 63 |
|
---|
| 64 | if (source) {
|
---|
| 65 | generatedMap.addMapping(mappings);
|
---|
| 66 | }
|
---|
| 67 | });
|
---|
| 68 | return generatedMap.toJSON();
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | function getSourceMappingURL(code) {
|
---|
| 72 | const lines = code.split(/^/m);
|
---|
| 73 | let match;
|
---|
| 74 |
|
---|
| 75 | for (let i = lines.length - 1; i >= 0; i--) {
|
---|
| 76 | match = lines[i].match(sourceMappingURLRegex);
|
---|
| 77 |
|
---|
| 78 | if (match) {
|
---|
| 79 | break;
|
---|
| 80 | }
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | const sourceMappingURL = match ? match[1] || match[2] || "" : null;
|
---|
| 84 | return {
|
---|
| 85 | sourceMappingURL: sourceMappingURL ? decodeURI(sourceMappingURL) : sourceMappingURL,
|
---|
| 86 | replacementString: match ? match[0] : null
|
---|
| 87 | };
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 | function getAbsolutePath(context, request, sourceRoot) {
|
---|
| 91 | if (sourceRoot) {
|
---|
| 92 | if (_path.default.isAbsolute(sourceRoot)) {
|
---|
| 93 | return _path.default.join(sourceRoot, request);
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | return _path.default.join(context, sourceRoot, request);
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | return _path.default.join(context, request);
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | function fetchFromDataURL(loaderContext, sourceURL) {
|
---|
| 103 | const dataURL = (0, _parseDataUrl.default)(sourceURL);
|
---|
| 104 |
|
---|
| 105 | if (dataURL) {
|
---|
| 106 | // https://tools.ietf.org/html/rfc4627
|
---|
| 107 | // JSON text SHALL be encoded in Unicode. The default encoding is UTF-8.
|
---|
| 108 | const encodingName = labelToName(dataURL.parameters.get("charset")) || "UTF-8";
|
---|
| 109 | return (0, _iconvLite.decode)(dataURL.body, encodingName);
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | throw new Error(`Failed to parse source map from "data" URL: ${sourceURL}`);
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | async function fetchFromFilesystem(loaderContext, sourceURL) {
|
---|
| 116 | let buffer;
|
---|
| 117 |
|
---|
| 118 | try {
|
---|
| 119 | buffer = await new Promise((resolve, reject) => {
|
---|
| 120 | loaderContext.fs.readFile(sourceURL, (error, data) => {
|
---|
| 121 | if (error) {
|
---|
| 122 | return reject(error);
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | return resolve(data);
|
---|
| 126 | });
|
---|
| 127 | });
|
---|
| 128 | } catch (error) {
|
---|
| 129 | throw new Error(`Failed to parse source map from '${sourceURL}' file: ${error}`);
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | return {
|
---|
| 133 | path: sourceURL,
|
---|
| 134 | data: buffer.toString()
|
---|
| 135 | };
|
---|
| 136 | }
|
---|
| 137 |
|
---|
| 138 | async function fetchPathsFromFilesystem(loaderContext, possibleRequests, errorsAccumulator = "") {
|
---|
| 139 | let result;
|
---|
| 140 |
|
---|
| 141 | try {
|
---|
| 142 | result = await fetchFromFilesystem(loaderContext, possibleRequests[0], errorsAccumulator);
|
---|
| 143 | } catch (error) {
|
---|
| 144 | // eslint-disable-next-line no-param-reassign
|
---|
| 145 | errorsAccumulator += `${error.message}\n\n`;
|
---|
| 146 | const [, ...tailPossibleRequests] = possibleRequests;
|
---|
| 147 |
|
---|
| 148 | if (tailPossibleRequests.length === 0) {
|
---|
| 149 | error.message = errorsAccumulator;
|
---|
| 150 | throw error;
|
---|
| 151 | }
|
---|
| 152 |
|
---|
| 153 | return fetchPathsFromFilesystem(loaderContext, tailPossibleRequests, errorsAccumulator);
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | return result;
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | async function fetchFromURL(loaderContext, context, url, sourceRoot, skipReading = false) {
|
---|
| 160 | // 1. It's an absolute url and it is not `windows` path like `C:\dir\file`
|
---|
| 161 | if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !_path.default.win32.isAbsolute(url)) {
|
---|
| 162 | const {
|
---|
| 163 | protocol
|
---|
| 164 | } = _url.default.parse(url);
|
---|
| 165 |
|
---|
| 166 | if (protocol === "data:") {
|
---|
| 167 | if (skipReading) {
|
---|
| 168 | return {
|
---|
| 169 | sourceURL: ""
|
---|
| 170 | };
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | const sourceContent = fetchFromDataURL(loaderContext, url);
|
---|
| 174 | return {
|
---|
| 175 | sourceURL: "",
|
---|
| 176 | sourceContent
|
---|
| 177 | };
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | if (skipReading) {
|
---|
| 181 | return {
|
---|
| 182 | sourceURL: url
|
---|
| 183 | };
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | if (protocol === "file:") {
|
---|
| 187 | const pathFromURL = _url.default.fileURLToPath(url);
|
---|
| 188 |
|
---|
| 189 | const sourceURL = _path.default.normalize(pathFromURL);
|
---|
| 190 |
|
---|
| 191 | const {
|
---|
| 192 | data: sourceContent
|
---|
| 193 | } = await fetchFromFilesystem(loaderContext, sourceURL);
|
---|
| 194 | return {
|
---|
| 195 | sourceURL,
|
---|
| 196 | sourceContent
|
---|
| 197 | };
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 | throw new Error(`Failed to parse source map: '${url}' URL is not supported`);
|
---|
| 201 | } // 2. It's a scheme-relative
|
---|
| 202 |
|
---|
| 203 |
|
---|
| 204 | if (/^\/\//.test(url)) {
|
---|
| 205 | throw new Error(`Failed to parse source map: '${url}' URL is not supported`);
|
---|
| 206 | } // 3. Absolute path
|
---|
| 207 |
|
---|
| 208 |
|
---|
| 209 | if (_path.default.isAbsolute(url)) {
|
---|
| 210 | let sourceURL = _path.default.normalize(url);
|
---|
| 211 |
|
---|
| 212 | let sourceContent;
|
---|
| 213 |
|
---|
| 214 | if (!skipReading) {
|
---|
| 215 | const possibleRequests = [sourceURL];
|
---|
| 216 |
|
---|
| 217 | if (url.startsWith("/")) {
|
---|
| 218 | possibleRequests.push(getAbsolutePath(context, sourceURL.slice(1), sourceRoot));
|
---|
| 219 | }
|
---|
| 220 |
|
---|
| 221 | const result = await fetchPathsFromFilesystem(loaderContext, possibleRequests);
|
---|
| 222 | sourceURL = result.path;
|
---|
| 223 | sourceContent = result.data;
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | return {
|
---|
| 227 | sourceURL,
|
---|
| 228 | sourceContent
|
---|
| 229 | };
|
---|
| 230 | } // 4. Relative path
|
---|
| 231 |
|
---|
| 232 |
|
---|
| 233 | const sourceURL = getAbsolutePath(context, url, sourceRoot);
|
---|
| 234 | let sourceContent;
|
---|
| 235 |
|
---|
| 236 | if (!skipReading) {
|
---|
| 237 | const {
|
---|
| 238 | data
|
---|
| 239 | } = await fetchFromFilesystem(loaderContext, sourceURL);
|
---|
| 240 | sourceContent = data;
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | return {
|
---|
| 244 | sourceURL,
|
---|
| 245 | sourceContent
|
---|
| 246 | };
|
---|
| 247 | } |
---|