mirror of https://github.com/webpack/webpack.git
				
				
				
			feat: extractSourceMap supports HTTP URLs (#19882)
This commit is contained in:
		
							parent
							
								
									cc8e6a195a
								
							
						
					
					
						commit
						df204b5f71
					
				|  | @ -264,6 +264,10 @@ makeSerializable( | ||||||
|  * @property {boolean=} extractSourceMap enable/disable extracting source map |  * @property {boolean=} extractSourceMap enable/disable extracting source map | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @typedef {(resourcePath: string, getLoaderContext: (resourcePath: string) => LoaderContext<EXPECTED_ANY>) => Promise<string | Buffer<ArrayBufferLike>>} ReadResource | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */ | /** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */ | ||||||
| const compilationHooksMap = new WeakMap(); | const compilationHooksMap = new WeakMap(); | ||||||
| 
 | 
 | ||||||
|  | @ -1023,43 +1027,76 @@ class NormalModule extends Module { | ||||||
| 				 * @param {LoaderContext<EXPECTED_ANY>} loaderContext the loader context | 				 * @param {LoaderContext<EXPECTED_ANY>} loaderContext the loader context | ||||||
| 				 * @param {string} resourcePath the resource Path | 				 * @param {string} resourcePath the resource Path | ||||||
| 				 * @param {(err: Error | null, result?: string | Buffer, sourceMap?: Result[1]) => void} callback callback | 				 * @param {(err: Error | null, result?: string | Buffer, sourceMap?: Result[1]) => void} callback callback | ||||||
|  | 				 * @returns {Promise<void>} | ||||||
| 				 */ | 				 */ | ||||||
| 				processResource: (loaderContext, resourcePath, callback) => { | 				processResource: async (loaderContext, resourcePath, callback) => { | ||||||
| 					const resource = loaderContext.resource; | 					/** @type {ReadResource} */ | ||||||
| 					const scheme = getScheme(resource); | 					const readResource = (resourcePath, getLoaderContext) => { | ||||||
|  | 						const scheme = getScheme(resourcePath); | ||||||
|  | 						return new Promise((resolve, reject) => { | ||||||
| 							hooks.readResource | 							hooks.readResource | ||||||
| 								.for(scheme) | 								.for(scheme) | ||||||
| 						.callAsync(loaderContext, async (err, result) => { | 								.callAsync(getLoaderContext(resourcePath), (err, result) => { | ||||||
| 							if (err) return callback(err); | 									if (err) { | ||||||
|  | 										reject(err); | ||||||
|  | 									} else { | ||||||
| 										if (typeof result !== "string" && !result) { | 										if (typeof result !== "string" && !result) { | ||||||
| 								return callback( | 											return reject( | ||||||
| 												new UnhandledSchemeError( | 												new UnhandledSchemeError( | ||||||
| 													/** @type {string} */ | 													/** @type {string} */ | ||||||
| 													(scheme), | 													(scheme), | ||||||
| 										resource | 													resourcePath | ||||||
| 												) | 												) | ||||||
| 											); | 											); | ||||||
| 										} | 										} | ||||||
|  | 										resolve(result); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 						}); | ||||||
|  | 					}; | ||||||
|  | 					try { | ||||||
|  | 						const result = await readResource( | ||||||
|  | 							resourcePath, | ||||||
|  | 							() => loaderContext | ||||||
|  | 						); | ||||||
| 						if ( | 						if ( | ||||||
| 							this.extractSourceMap && | 							this.extractSourceMap && | ||||||
| 							(this.useSourceMap || this.useSimpleSourceMap) | 							(this.useSourceMap || this.useSimpleSourceMap) | ||||||
| 						) { | 						) { | ||||||
| 							try { | 							try { | ||||||
| 									const { source, sourceMap, fileDependencies } = | 								const { source, sourceMap } = await getExtractSourceMap()( | ||||||
| 										await getExtractSourceMap()(result, resourcePath, fs); | 									result, | ||||||
| 									if (this.buildInfo && this.buildInfo.fileDependencies) { | 									resourcePath, | ||||||
| 										this.buildInfo.fileDependencies.addAll(fileDependencies); | 									/** @type {ReadResource} */ | ||||||
| 									} | 									(resourcePath) => | ||||||
|  | 										readResource( | ||||||
|  | 											resourcePath, | ||||||
|  | 											(resourcePath) => | ||||||
|  | 												/** @type {LoaderContext<EXPECTED_ANY>} */ ({ | ||||||
|  | 													addDependency(dependency) { | ||||||
|  | 														loaderContext.addDependency(dependency); | ||||||
|  | 													}, | ||||||
|  | 													fs: loaderContext.fs, | ||||||
|  | 													_module: undefined, | ||||||
|  | 													resourcePath, | ||||||
|  | 													resource: resourcePath | ||||||
|  | 												}) | ||||||
|  | 										).catch((err) => { | ||||||
|  | 											throw new Error( | ||||||
|  | 												`Failed to parse source map. ${/** @type {Error} */ (err).message}` | ||||||
|  | 											); | ||||||
|  | 										}) | ||||||
|  | 								); | ||||||
| 								return callback(null, source, sourceMap); | 								return callback(null, source, sourceMap); | ||||||
| 							} catch (err) { | 							} catch (err) { | ||||||
| 									this.addWarning( | 								this.addWarning(new ModuleWarning(/** @type {Error} */ (err))); | ||||||
| 										new ModuleWarning(/** @type {Error} */ (err)) |  | ||||||
| 									); |  | ||||||
| 								return callback(null, result); | 								return callback(null, result); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						return callback(null, result); | 						return callback(null, result); | ||||||
| 						}); | 					} catch (error) { | ||||||
|  | 						return callback(/** @type {Error} */ (error)); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			}, | 			}, | ||||||
| 			(err, result) => { | 			(err, result) => { | ||||||
|  |  | ||||||
|  | @ -35,6 +35,7 @@ class DataUriPlugin { | ||||||
| 							resourceData.data.encodedContent = match[4] || ""; | 							resourceData.data.encodedContent = match[4] || ""; | ||||||
| 						} | 						} | ||||||
| 					}); | 					}); | ||||||
|  | 
 | ||||||
| 				NormalModule.getCompilationHooks(compilation) | 				NormalModule.getCompilationHooks(compilation) | ||||||
| 					.readResourceForScheme.for("data") | 					.readResourceForScheme.for("data") | ||||||
| 					.tap(PLUGIN_NAME, (resource) => decodeDataURI(resource)); | 					.tap(PLUGIN_NAME, (resource) => decodeDataURI(resource)); | ||||||
|  |  | ||||||
|  | @ -40,8 +40,11 @@ class FileUriPlugin { | ||||||
| 					.for(undefined) | 					.for(undefined) | ||||||
| 					.tapAsync(PLUGIN_NAME, (loaderContext, callback) => { | 					.tapAsync(PLUGIN_NAME, (loaderContext, callback) => { | ||||||
| 						const { resourcePath } = loaderContext; | 						const { resourcePath } = loaderContext; | ||||||
|  | 						loaderContext.fs.readFile(resourcePath, (err, result) => { | ||||||
|  | 							if (err) return callback(err); | ||||||
| 							loaderContext.addDependency(resourcePath); | 							loaderContext.addDependency(resourcePath); | ||||||
| 						loaderContext.fs.readFile(resourcePath, callback); | 							callback(null, result); | ||||||
|  | 						}); | ||||||
| 					}); | 					}); | ||||||
| 			} | 			} | ||||||
| 		); | 		); | ||||||
|  |  | ||||||
|  | @ -1199,8 +1199,10 @@ Run build with un-frozen lockfile to automatically fix lockfile.` | ||||||
| 							getInfo(resource, (err, _result) => { | 							getInfo(resource, (err, _result) => { | ||||||
| 								if (err) return callback(err); | 								if (err) return callback(err); | ||||||
| 								const result = /** @type {Info} */ (_result); | 								const result = /** @type {Info} */ (_result); | ||||||
|  | 								if (module) { | ||||||
| 									/** @type {BuildInfo} */ | 									/** @type {BuildInfo} */ | ||||||
| 									(module.buildInfo).resourceIntegrity = result.entry.integrity; | 									(module.buildInfo).resourceIntegrity = result.entry.integrity; | ||||||
|  | 								} | ||||||
| 								callback(null, result.content); | 								callback(null, result.content); | ||||||
| 							}) | 							}) | ||||||
| 						); | 						); | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ | ||||||
| 
 | 
 | ||||||
| const path = require("path"); | const path = require("path"); | ||||||
| const urlUtils = require("url"); | const urlUtils = require("url"); | ||||||
| const { decodeDataURI } = require("./dataURL"); |  | ||||||
| const { isAbsolute, join } = require("./fs"); | const { isAbsolute, join } = require("./fs"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("../../declarations/WebpackOptions").RuleSetRule["extractSourceMap"]} ExtractSourceMapOptions */ | /** @typedef {import("../../declarations/WebpackOptions").RuleSetRule["extractSourceMap"]} ExtractSourceMapOptions */ | ||||||
|  | @ -19,6 +18,10 @@ const { isAbsolute, join } = require("./fs"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("webpack-sources").RawSourceMap} RawSourceMap */ | /** @typedef {import("webpack-sources").RawSourceMap} RawSourceMap */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @typedef {(resourcePath: string) => Promise<string | Buffer<ArrayBufferLike>>} ReadResource | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * @typedef {object} SourceMappingURL |  * @typedef {object} SourceMappingURL | ||||||
|  * @property {string} sourceMappingURL |  * @property {string} sourceMappingURL | ||||||
|  | @ -71,22 +74,21 @@ function getSourceMappingURL(code) { | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Get absolute path for source file |  * Get absolute path for source file | ||||||
|  * @param {InputFileSystem} fs file system |  | ||||||
|  * @param {string} context context directory |  * @param {string} context context directory | ||||||
|  * @param {string} request file request |  * @param {string} request file request | ||||||
|  * @param {string} sourceRoot source root directory |  * @param {string} sourceRoot source root directory | ||||||
|  * @returns {string} absolute path |  * @returns {string} absolute path | ||||||
|  */ |  */ | ||||||
| function getAbsolutePath(fs, context, request, sourceRoot) { | function getAbsolutePath(context, request, sourceRoot) { | ||||||
| 	if (sourceRoot) { | 	if (sourceRoot) { | ||||||
| 		if (isAbsolute(sourceRoot)) { | 		if (isAbsolute(sourceRoot)) { | ||||||
| 			return join(fs, sourceRoot, request); | 			return join(undefined, sourceRoot, request); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return join(fs, join(fs, context, sourceRoot), request); | 		return join(undefined, join(undefined, context, sourceRoot), request); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return join(fs, context, request); | 	return join(undefined, context, request); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | @ -98,76 +100,22 @@ function isURL(value) { | ||||||
| 	return validProtocolPattern.test(value) && !path.win32.isAbsolute(value); | 	return validProtocolPattern.test(value) && !path.win32.isAbsolute(value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * Fetch source content from data URL |  | ||||||
|  * @param {InputFileSystem} fs file system |  | ||||||
|  * @param {string} sourceURL data URL |  | ||||||
|  * @returns {string} source content promise |  | ||||||
|  */ |  | ||||||
| function fetchFromDataURL(fs, sourceURL) { |  | ||||||
| 	const content = decodeDataURI(sourceURL); |  | ||||||
| 
 |  | ||||||
| 	if (content) { |  | ||||||
| 		return content.toString("utf8"); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	throw new Error(`Failed to parse source map from "data" URL: ${sourceURL}`); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Fetch source content from file system |  | ||||||
|  * @param {InputFileSystem} fs file system |  | ||||||
|  * @param {string} sourceURL file URL |  | ||||||
|  * @returns {Promise<{path: string, data?: string}>} source content promise |  | ||||||
|  */ |  | ||||||
| async function fetchFromFilesystem(fs, sourceURL) { |  | ||||||
| 	let buffer; |  | ||||||
| 
 |  | ||||||
| 	if (isURL(sourceURL)) { |  | ||||||
| 		return { path: sourceURL }; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	try { |  | ||||||
| 		buffer = await new Promise((resolve, reject) => { |  | ||||||
| 			fs.readFile( |  | ||||||
| 				sourceURL, |  | ||||||
| 				( |  | ||||||
| 					/** @type {Error | null} */ error, |  | ||||||
| 					/** @type {Buffer<ArrayBufferLike> | undefined} */ data |  | ||||||
| 				) => { |  | ||||||
| 					if (error) { |  | ||||||
| 						return reject(error); |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					return resolve(data); |  | ||||||
| 				} |  | ||||||
| 			); |  | ||||||
| 		}); |  | ||||||
| 	} catch (error) { |  | ||||||
| 		throw new Error( |  | ||||||
| 			`Failed to parse source map from '${sourceURL}' file: ${error}` |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return { path: sourceURL, data: buffer.toString() }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Fetch from multiple possible file paths |  * Fetch from multiple possible file paths | ||||||
|  * @param {InputFileSystem} fs file system |  * @param {ReadResource} readResource read resource function | ||||||
|  * @param {string[]} possibleRequests array of possible file paths |  * @param {string[]} possibleRequests array of possible file paths | ||||||
|  * @param {string} errorsAccumulator accumulated error messages |  * @param {string} errorsAccumulator accumulated error messages | ||||||
|  * @returns {Promise<{path: string, data?: string}>} source content promise |  * @returns {Promise<{path: string, data?: string}>} source content promise | ||||||
|  */ |  */ | ||||||
| async function fetchPathsFromFilesystem( | async function fetchPathsFromURL( | ||||||
| 	fs, | 	readResource, | ||||||
| 	possibleRequests, | 	possibleRequests, | ||||||
| 	errorsAccumulator = "" | 	errorsAccumulator = "" | ||||||
| ) { | ) { | ||||||
| 	let result; | 	let result; | ||||||
| 
 | 
 | ||||||
| 	try { | 	try { | ||||||
| 		result = await fetchFromFilesystem(fs, possibleRequests[0]); | 		result = await readResource(possibleRequests[0]); | ||||||
| 	} catch (error) { | 	} catch (error) { | ||||||
| 		errorsAccumulator += `${/** @type {Error} */ (error).message}\n\n`; | 		errorsAccumulator += `${/** @type {Error} */ (error).message}\n\n`; | ||||||
| 
 | 
 | ||||||
|  | @ -179,63 +127,55 @@ async function fetchPathsFromFilesystem( | ||||||
| 			throw error; | 			throw error; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return fetchPathsFromFilesystem( | 		return fetchPathsFromURL( | ||||||
| 			fs, | 			readResource, | ||||||
| 			tailPossibleRequests, | 			tailPossibleRequests, | ||||||
| 			errorsAccumulator | 			errorsAccumulator | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return { | ||||||
|  | 		path: possibleRequests[0], | ||||||
|  | 		data: result.toString("utf8") | ||||||
|  | 	}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Fetch source content from URL |  * Fetch source content from URL | ||||||
|  * @param {InputFileSystem} fs file system |  * @param {ReadResource} readResource The read resource function | ||||||
|  * @param {string} context context directory |  * @param {string} context context directory | ||||||
|  * @param {string} url source URL |  * @param {string} url source URL | ||||||
|  * @param {string=} sourceRoot source root directory |  * @param {string=} sourceRoot source root directory | ||||||
|  * @param {boolean=} skipReading whether to skip reading file content |  * @param {boolean=} skipReading whether to skip reading file content | ||||||
|  * @returns {Promise<{sourceURL: string, sourceContent?: string}>} source content promise |  * @returns {Promise<{sourceURL: string, sourceContent?: string | Buffer<ArrayBufferLike>}>} source content promise | ||||||
|  */ |  */ | ||||||
| async function fetchFromURL(fs, context, url, sourceRoot, skipReading = false) { | async function fetchFromURL( | ||||||
|  | 	readResource, | ||||||
|  | 	context, | ||||||
|  | 	url, | ||||||
|  | 	sourceRoot, | ||||||
|  | 	skipReading = false | ||||||
|  | ) { | ||||||
| 	// 1. It's an absolute url and it is not `windows` path like `C:\dir\file`
 | 	// 1. It's an absolute url and it is not `windows` path like `C:\dir\file`
 | ||||||
| 	if (isURL(url)) { | 	if (isURL(url)) { | ||||||
| 		// eslint-disable-next-line n/no-deprecated-api
 | 		// eslint-disable-next-line n/no-deprecated-api
 | ||||||
| 		const { protocol } = urlUtils.parse(url); | 		const { protocol } = urlUtils.parse(url); | ||||||
| 
 |  | ||||||
| 		if (protocol === "data:") { | 		if (protocol === "data:") { | ||||||
| 			if (skipReading) { | 			const sourceContent = skipReading ? "" : await readResource(url); | ||||||
| 				return { sourceURL: "" }; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			const sourceContent = fetchFromDataURL(fs, url); |  | ||||||
| 
 | 
 | ||||||
| 			return { sourceURL: "", sourceContent }; | 			return { sourceURL: "", sourceContent }; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (skipReading) { |  | ||||||
| 			return { sourceURL: url }; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (protocol === "file:") { | 		if (protocol === "file:") { | ||||||
| 			const pathFromURL = urlUtils.fileURLToPath(url); | 			const pathFromURL = urlUtils.fileURLToPath(url); | ||||||
| 			const sourceURL = path.normalize(pathFromURL); | 			const sourceURL = path.normalize(pathFromURL); | ||||||
| 			const { data: sourceContent } = await fetchFromFilesystem(fs, sourceURL); | 			const sourceContent = skipReading ? "" : await readResource(sourceURL); | ||||||
| 
 | 
 | ||||||
| 			return { sourceURL, sourceContent }; | 			return { sourceURL, sourceContent }; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		throw new Error( | 		const sourceContent = skipReading ? "" : await readResource(url); | ||||||
| 			`Failed to parse source map: '${url}' URL is not supported` | 		return { sourceURL: url, sourceContent }; | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// 2. It's a scheme-relative
 |  | ||||||
| 	if (/^\/\//.test(url)) { |  | ||||||
| 		throw new Error( |  | ||||||
| 			`Failed to parse source map: '${url}' URL is not supported` |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// 3. Absolute path
 | 	// 3. Absolute path
 | ||||||
|  | @ -249,11 +189,11 @@ async function fetchFromURL(fs, context, url, sourceRoot, skipReading = false) { | ||||||
| 
 | 
 | ||||||
| 			if (url.startsWith("/")) { | 			if (url.startsWith("/")) { | ||||||
| 				possibleRequests.push( | 				possibleRequests.push( | ||||||
| 					getAbsolutePath(fs, context, sourceURL.slice(1), sourceRoot || "") | 					getAbsolutePath(context, sourceURL.slice(1), sourceRoot || "") | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			const result = await fetchPathsFromFilesystem(fs, possibleRequests); | 			const result = await fetchPathsFromURL(readResource, possibleRequests); | ||||||
| 
 | 
 | ||||||
| 			sourceURL = result.path; | 			sourceURL = result.path; | ||||||
| 			sourceContent = result.data; | 			sourceContent = result.data; | ||||||
|  | @ -263,14 +203,11 @@ async function fetchFromURL(fs, context, url, sourceRoot, skipReading = false) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// 4. Relative path
 | 	// 4. Relative path
 | ||||||
| 	const sourceURL = getAbsolutePath(fs, context, url, sourceRoot || ""); | 	const sourceURL = getAbsolutePath(context, url, sourceRoot || ""); | ||||||
| 
 |  | ||||||
| 	let sourceContent; | 	let sourceContent; | ||||||
| 
 | 
 | ||||||
| 	if (!skipReading) { | 	if (!skipReading) { | ||||||
| 		const { data } = await fetchFromFilesystem(fs, sourceURL); | 		sourceContent = await readResource(sourceURL); | ||||||
| 
 |  | ||||||
| 		sourceContent = data; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return { sourceURL, sourceContent }; | 	return { sourceURL, sourceContent }; | ||||||
|  | @ -280,10 +217,10 @@ async function fetchFromURL(fs, context, url, sourceRoot, skipReading = false) { | ||||||
|  * Extract source map from code content |  * Extract source map from code content | ||||||
|  * @param {string | Buffer<ArrayBufferLike>} stringOrBuffer The input code content as string or buffer |  * @param {string | Buffer<ArrayBufferLike>} stringOrBuffer The input code content as string or buffer | ||||||
|  * @param {string} resourcePath The path to the resource file |  * @param {string} resourcePath The path to the resource file | ||||||
|  * @param {InputFileSystem} fs The file system interface for reading files |  * @param {ReadResource} readResource The read resource function | ||||||
|  * @returns {Promise<{source: string | Buffer<ArrayBufferLike>, sourceMap: string | RawSourceMap | undefined, fileDependencies: string[]}>} Promise resolving to extracted source map information |  * @returns {Promise<{source: string | Buffer<ArrayBufferLike>, sourceMap: string | RawSourceMap | undefined}>} Promise resolving to extracted source map information | ||||||
|  */ |  */ | ||||||
| async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | async function extractSourceMap(stringOrBuffer, resourcePath, readResource) { | ||||||
| 	const input = | 	const input = | ||||||
| 		typeof stringOrBuffer === "string" | 		typeof stringOrBuffer === "string" | ||||||
| 			? stringOrBuffer | 			? stringOrBuffer | ||||||
|  | @ -291,8 +228,7 @@ async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | ||||||
| 	const inputSourceMap = undefined; | 	const inputSourceMap = undefined; | ||||||
| 	const output = { | 	const output = { | ||||||
| 		source: stringOrBuffer, | 		source: stringOrBuffer, | ||||||
| 		sourceMap: inputSourceMap, | 		sourceMap: inputSourceMap | ||||||
| 		fileDependencies: /** @type {string[]} */ ([]) |  | ||||||
| 	}; | 	}; | ||||||
| 	const { sourceMappingURL, replacementString } = getSourceMappingURL(input); | 	const { sourceMappingURL, replacementString } = getSourceMappingURL(input); | ||||||
| 
 | 
 | ||||||
|  | @ -303,21 +239,19 @@ async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | ||||||
| 	const baseContext = path.dirname(resourcePath); | 	const baseContext = path.dirname(resourcePath); | ||||||
| 
 | 
 | ||||||
| 	const { sourceURL, sourceContent } = await fetchFromURL( | 	const { sourceURL, sourceContent } = await fetchFromURL( | ||||||
| 		fs, | 		readResource, | ||||||
| 		baseContext, | 		baseContext, | ||||||
| 		sourceMappingURL | 		sourceMappingURL | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	if (sourceURL) { |  | ||||||
| 		output.fileDependencies.push(/** @type {string} */ (sourceURL)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!sourceContent) { | 	if (!sourceContent) { | ||||||
| 		return output; | 		return output; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** @type {RawSourceMap} */ | 	/** @type {RawSourceMap} */ | ||||||
| 	const map = JSON.parse(sourceContent.replace(/^\)\]\}'/, "")); | 	const map = JSON.parse( | ||||||
|  | 		sourceContent.toString("utf8").replace(/^\)\]\}'/, "") | ||||||
|  | 	); | ||||||
| 
 | 
 | ||||||
| 	const context = sourceURL ? path.dirname(sourceURL) : baseContext; | 	const context = sourceURL ? path.dirname(sourceURL) : baseContext; | ||||||
| 
 | 
 | ||||||
|  | @ -335,7 +269,7 @@ async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | ||||||
| 				// This is necessary so that for sourceMaps with the same file structure in sources, name collisions do not occur.
 | 				// This is necessary so that for sourceMaps with the same file structure in sources, name collisions do not occur.
 | ||||||
| 				// https://github.com/webpack-contrib/source-map-loader/issues/51
 | 				// https://github.com/webpack-contrib/source-map-loader/issues/51
 | ||||||
| 				let { sourceURL, sourceContent } = await fetchFromURL( | 				let { sourceURL, sourceContent } = await fetchFromURL( | ||||||
| 					fs, | 					readResource, | ||||||
| 					context, | 					context, | ||||||
| 					source, | 					source, | ||||||
| 					map.sourceRoot, | 					map.sourceRoot, | ||||||
|  | @ -344,8 +278,6 @@ async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | ||||||
| 
 | 
 | ||||||
| 				if (skipReading) { | 				if (skipReading) { | ||||||
| 					sourceContent = originalSourceContent; | 					sourceContent = originalSourceContent; | ||||||
| 				} else if (sourceURL && !isURL(sourceURL)) { |  | ||||||
| 					output.fileDependencies.push(/** @type {string} */ (sourceURL)); |  | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// Return original value of `source` when error happens
 | 				// Return original value of `source` when error happens
 | ||||||
|  | @ -366,7 +298,9 @@ async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | ||||||
| 		const { sourceURL, sourceContent } = source; | 		const { sourceURL, sourceContent } = source; | ||||||
| 
 | 
 | ||||||
| 		newMap.sources.push(sourceURL || ""); | 		newMap.sources.push(sourceURL || ""); | ||||||
| 		newMap.sourcesContent.push(sourceContent || ""); | 		newMap.sourcesContent.push( | ||||||
|  | 			sourceContent ? sourceContent.toString("utf8") : "" | ||||||
|  | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const sourcesContentIsEmpty = | 	const sourcesContentIsEmpty = | ||||||
|  | @ -378,8 +312,7 @@ async function extractSourceMap(stringOrBuffer, resourcePath, fs) { | ||||||
| 
 | 
 | ||||||
| 	return { | 	return { | ||||||
| 		source: input.replace(replacementString, ""), | 		source: input.replace(replacementString, ""), | ||||||
| 		sourceMap: /** @type {RawSourceMap} */ (newMap), | 		sourceMap: /** @type {RawSourceMap} */ (newMap) | ||||||
| 		fileDependencies: output.fileDependencies |  | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | "use strict"; | ||||||
|  | 
 | ||||||
|  | const fs = require("fs"); | ||||||
|  | const path = require("path"); | ||||||
|  | 
 | ||||||
|  | require("./test4"); | ||||||
|  | 
 | ||||||
|  | it("should extract source map - 4", () => { | ||||||
|  | 	const fileData = fs.readFileSync(path.resolve(__dirname, "bundle3.js.map")).toString("utf-8"); | ||||||
|  | 	const { sources } = JSON.parse(fileData); | ||||||
|  | 	expect(sources.includes("webpack:///antd/./components/button/index.tsx")).toBe(true); | ||||||
|  | }); | ||||||
|  | @ -0,0 +1,4 @@ | ||||||
|  | { | ||||||
|  |   "https://cdnjs.cloudflare.com/ajax/libs/antd/5.27.3/antd.min.js.map": { "integrity": "sha512-dV8AVOy1aVA2CRfd5/ZKySqR8i/VcIZCfJbstL+kyuzioyu/652hEL+KRrqVutRx8y5CTwFskQVQ79rFy5VRLg==", "contentType": "application/octet-stream; charset=utf-8" }, | ||||||
|  |   "version": 1 | ||||||
|  | } | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | const a = 1; | ||||||
|  | // comment
 | ||||||
|  | //#sourceMappingURL=https://cdnjs.cloudflare.com/ajax/libs/antd/5.27.3/antd.min.js.map
 | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
|  | const path = require("path"); | ||||||
|  | 
 | ||||||
| /** @type {import("../../../../").Configuration[]} */ | /** @type {import("../../../../").Configuration[]} */ | ||||||
| module.exports = [ | module.exports = [ | ||||||
| 	{ | 	{ | ||||||
|  | @ -38,6 +40,26 @@ module.exports = [ | ||||||
| 			] | 			] | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
|  | 	{ | ||||||
|  | 		target: "node", | ||||||
|  | 		entry: "./extract4", | ||||||
|  | 		devtool: "source-map", | ||||||
|  | 		experiments: { | ||||||
|  | 			buildHttp: { | ||||||
|  | 				allowedUris: [() => true], | ||||||
|  | 				lockfileLocation: path.resolve(__dirname, "./lock-files/lock.json"), | ||||||
|  | 				cacheLocation: path.resolve(__dirname, "./lock-files/test"), | ||||||
|  | 				frozen: false | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 		module: { | ||||||
|  | 			rules: [ | ||||||
|  | 				{ | ||||||
|  | 					extractSourceMap: true | ||||||
|  | 				} | ||||||
|  | 			] | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		entry: "./remove-comment", | 		entry: "./remove-comment", | ||||||
| 		devtool: "source-map", | 		devtool: "source-map", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue