From 3dfa75e60d0af5d329f96703741a13d680e1ac89 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Fri, 7 Jul 2017 12:51:55 +0200 Subject: [PATCH] generate source map names globally --- lib/SourceMapDevToolPlugin.js | 64 +++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/lib/SourceMapDevToolPlugin.js b/lib/SourceMapDevToolPlugin.js index 2aec14de0dc..5f001b60dd8 100644 --- a/lib/SourceMapDevToolPlugin.js +++ b/lib/SourceMapDevToolPlugin.js @@ -46,8 +46,7 @@ class SourceMapDevToolPlugin { compiler.plugin("compilation", compilation => { new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); compilation.plugin("after-optimize-chunk-assets", function(chunks) { - let allModules = []; - let allModuleFilenames = []; + const moduleToSourceNameMapping = new Map(); const tasks = []; chunks.forEach(function(chunk) { chunk.files.filter(ModuleFilenameHelpers.matchObject.bind(undefined, options)).map(function(file) { @@ -84,40 +83,61 @@ class SourceMapDevToolPlugin { const module = compilation.findModule(source); return module || source; }); - const moduleFilenames = modules.map(module => ModuleFilenameHelpers.createFilename(module, moduleFilenameTemplate, requestShortener)); + for(const module of modules) { + if(!moduleToSourceNameMapping.get(module)) { + moduleToSourceNameMapping.set(module, ModuleFilenameHelpers.createFilename(module, moduleFilenameTemplate, requestShortener)); + } + } task.modules = modules; - task.moduleFilenames = moduleFilenames; return task; }).forEach(task => { - allModules = allModules.concat(task.modules); - allModuleFilenames = allModuleFilenames.concat(task.moduleFilenames); tasks.push(task); }); }); - allModuleFilenames = ModuleFilenameHelpers.replaceDuplicates(allModuleFilenames, (filename, i) => ModuleFilenameHelpers.createFilename(allModules[i], fallbackModuleFilenameTemplate, requestShortener), (ai, bi) => { - let a = allModules[ai]; - let b = allModules[bi]; - a = !a ? "" : typeof a === "string" ? a : a.identifier(); - b = !b ? "" : typeof b === "string" ? b : b.identifier(); - return a.length - b.length; - }); - allModuleFilenames = ModuleFilenameHelpers.replaceDuplicates(allModuleFilenames, (filename, i, n) => { - for(let j = 0; j < n; j++) - filename += "*"; - return filename; - }); - tasks.forEach(task => { - task.moduleFilenames = allModuleFilenames.slice(0, task.moduleFilenames.length); - allModuleFilenames = allModuleFilenames.slice(task.moduleFilenames.length); + const usedNamesSet = new Set(moduleToSourceNameMapping.values()); + const conflictDetectionSet = new Set(); + + // all modules in defined order (longest identifier first) + const allModules = Array.from(moduleToSourceNameMapping.keys()).sort((a, b) => { + const ai = typeof a === "string" ? a : a.identifier(); + const bi = typeof b === "string" ? b : b.identifier(); + return ai.length - bi.length; }); + + // find modules with conflicting source names + for(const module of allModules) { + let sourceName = moduleToSourceNameMapping.get(module); + let hasName = conflictDetectionSet.has(sourceName); + if(!hasName) { + conflictDetectionSet.add(sourceName); + continue; + } + + // try the fallback name first + sourceName = ModuleFilenameHelpers.createFilename(module, fallbackModuleFilenameTemplate, requestShortener); + hasName = usedNamesSet.has(sourceName); + if(!hasName) { + moduleToSourceNameMapping.set(module, sourceName); + usedNamesSet.add(sourceName); + continue; + } + + // elsewise just append stars until we have a valid name + do { + sourceName += "*"; + hasName = usedNamesSet.has(sourceName); + } while(hasName); + moduleToSourceNameMapping.set(module, sourceName); + usedNamesSet.add(sourceName); + } tasks.forEach(function(task) { const chunk = task.chunk; const file = task.file; const asset = task.asset; const sourceMap = task.sourceMap; const source = task.source; - const moduleFilenames = task.moduleFilenames; const modules = task.modules; + const moduleFilenames = modules.map(m => moduleToSourceNameMapping.get(m)); sourceMap.sources = moduleFilenames; if(sourceMap.sourcesContent && !options.noSources) { sourceMap.sourcesContent = sourceMap.sourcesContent.map((content, i) => `${content}\n\n\n${ModuleFilenameHelpers.createFooter(modules[i], requestShortener)}`);