webpack-sources
Advanced tools
| /* | ||
| MIT License http://www.opensource.org/licenses/mit-license.php | ||
| Author Tobias Koppers @sokra | ||
| */ | ||
| "use strict"; | ||
| const SourceNode = require("source-map").SourceNode; | ||
| const SourceMapConsumer = require("source-map").SourceMapConsumer; | ||
| const applySourceMap = function( | ||
| sourceNode, | ||
| sourceMapConsumer, | ||
| sourceFile, | ||
| removeGeneratedCodeForSourceFile | ||
| ) { | ||
| // The following notations are used to name stuff: | ||
| // Left <------------> Middle <-------------------> Right | ||
| // Input arguments: | ||
| // sourceNode - Code mapping from Left to Middle | ||
| // sourceFile - Name of a Middle file | ||
| // sourceMapConsumer - Code mapping from Middle to Right | ||
| // Variables: | ||
| // l2m m2r | ||
| // Left <-----------------------------------------> Right | ||
| // Variables: | ||
| // l2r | ||
| const l2rResult = new SourceNode(); | ||
| const l2rOutput = []; | ||
| const middleSourceContents = {}; | ||
| const m2rMappingsByLine = {}; | ||
| const rightSourceContentsSet = {}; | ||
| const rightSourceContentsLines = {}; | ||
| // Store all mappings by generated line | ||
| sourceMapConsumer.eachMapping( | ||
| function(mapping) { | ||
| (m2rMappingsByLine[mapping.generatedLine] = | ||
| m2rMappingsByLine[mapping.generatedLine] || []).push(mapping); | ||
| }, | ||
| null, | ||
| SourceMapConsumer.GENERATED_ORDER | ||
| ); | ||
| // Store all source contents | ||
| sourceNode.walkSourceContents(function(source, content) { | ||
| middleSourceContents["$" + source] = content; | ||
| }); | ||
| const middleSource = middleSourceContents["$" + sourceFile]; | ||
| const middleSourceLines = middleSource ? middleSource.split("\n") : undefined; | ||
| // Walk all left to middle mappings | ||
| sourceNode.walk(function(chunk, middleMapping) { | ||
| // Find a mapping from middle to right | ||
| if ( | ||
| middleMapping.source === sourceFile && | ||
| middleMapping.line && | ||
| m2rMappingsByLine[middleMapping.line] | ||
| ) { | ||
| let m2rBestFit; | ||
| const m2rMappings = m2rMappingsByLine[middleMapping.line]; | ||
| // Note: if this becomes a performance problem, use binary search | ||
| for (let i = 0; i < m2rMappings.length; i++) { | ||
| if (m2rMappings[i].generatedColumn <= middleMapping.column) { | ||
| m2rBestFit = m2rMappings[i]; | ||
| } | ||
| } | ||
| if (m2rBestFit) { | ||
| let allowMiddleName = false; | ||
| let middleLine; | ||
| let rightSourceContent; | ||
| let rightSourceContentLines; | ||
| const rightSource = m2rBestFit.source; | ||
| // Check if we have middle and right source for this mapping | ||
| // Then we could have an "identify" mapping | ||
| if ( | ||
| middleSourceLines && | ||
| rightSource && | ||
| (middleLine = middleSourceLines[m2rBestFit.generatedLine - 1]) && | ||
| ((rightSourceContentLines = rightSourceContentsLines[rightSource]) || | ||
| (rightSourceContent = sourceMapConsumer.sourceContentFor( | ||
| rightSource, | ||
| true | ||
| ))) | ||
| ) { | ||
| if (!rightSourceContentLines) { | ||
| rightSourceContentLines = rightSourceContentsLines[ | ||
| rightSource | ||
| ] = rightSourceContent.split("\n"); | ||
| } | ||
| const rightLine = | ||
| rightSourceContentLines[m2rBestFit.originalLine - 1]; | ||
| if (rightLine) { | ||
| const offset = middleMapping.column - m2rBestFit.generatedColumn; | ||
| if (offset > 0) { | ||
| const middlePart = middleLine.slice( | ||
| m2rBestFit.generatedColumn, | ||
| middleMapping.column | ||
| ); | ||
| const rightPart = rightLine.slice( | ||
| m2rBestFit.originalColumn, | ||
| m2rBestFit.originalColumn + offset | ||
| ); | ||
| if (middlePart === rightPart) { | ||
| // When original and generated code is equal we assume we have an "identity" mapping | ||
| // In this case we can offset the original position | ||
| m2rBestFit = Object.assign({}, m2rBestFit, { | ||
| originalColumn: m2rBestFit.originalColumn + offset, | ||
| generatedColumn: middleMapping.column, | ||
| name: undefined | ||
| }); | ||
| } | ||
| } | ||
| if (!m2rBestFit.name && middleMapping.name) { | ||
| allowMiddleName = | ||
| rightLine.slice( | ||
| m2rBestFit.originalColumn, | ||
| m2rBestFit.originalColumn + middleMapping.name.length | ||
| ) === middleMapping.name; | ||
| } | ||
| } | ||
| } | ||
| // Construct a left to right node from the found middle to right mapping | ||
| const source = m2rBestFit.source; | ||
| l2rOutput.push( | ||
| new SourceNode( | ||
| m2rBestFit.originalLine, | ||
| m2rBestFit.originalColumn, | ||
| source, | ||
| chunk, | ||
| allowMiddleName ? middleMapping.name : m2rBestFit.name | ||
| ) | ||
| ); | ||
| // Set the source contents once | ||
| if (!("$" + source in rightSourceContentsSet)) { | ||
| rightSourceContentsSet["$" + source] = true; | ||
| const sourceContent = sourceMapConsumer.sourceContentFor(source); | ||
| if (sourceContent) { | ||
| l2rResult.setSourceContent(source, sourceContent); | ||
| } | ||
| } | ||
| return; | ||
| } | ||
| } | ||
| if ( | ||
| (removeGeneratedCodeForSourceFile && | ||
| middleMapping.source === sourceFile) || | ||
| !middleMapping.source | ||
| ) { | ||
| // Construct a left to middle node with only generated code | ||
| // Because user do not want mappings to middle sources | ||
| // Or this chunk has no mapping | ||
| l2rOutput.push(chunk); | ||
| return; | ||
| } | ||
| // Construct a left to middle node | ||
| const source = middleMapping.source; | ||
| l2rOutput.push( | ||
| new SourceNode( | ||
| middleMapping.line, | ||
| middleMapping.column, | ||
| source, | ||
| chunk, | ||
| middleMapping.name | ||
| ) | ||
| ); | ||
| if ("$" + source in middleSourceContents) { | ||
| if (!("$" + source in rightSourceContentsSet)) { | ||
| l2rResult.setSourceContent(source, middleSourceContents["$" + source]); | ||
| delete middleSourceContents["$" + source]; | ||
| } | ||
| } | ||
| }); | ||
| // Put output into the resulting SourceNode | ||
| l2rResult.add(l2rOutput); | ||
| return l2rResult; | ||
| }; | ||
| module.exports = applySourceMap; |
+29
-25
@@ -13,23 +13,2 @@ /* | ||
| function cloneAndPrefix(node, prefix, append) { | ||
| if (typeof node === "string") { | ||
| let result = node.replace(REPLACE_REGEX, "\n" + prefix); | ||
| if (append.length > 0) result = append.pop() + result; | ||
| if (/\n$/.test(node)) append.push(prefix); | ||
| return result; | ||
| } else { | ||
| const newNode = new SourceNode( | ||
| node.line, | ||
| node.column, | ||
| node.source, | ||
| node.children.map(function(node) { | ||
| return cloneAndPrefix(node, prefix, append); | ||
| }), | ||
| node.name | ||
| ); | ||
| newNode.sourceContents = node.sourceContents; | ||
| return newNode; | ||
| } | ||
| } | ||
| class PrefixSource extends Source { | ||
@@ -59,6 +38,31 @@ constructor(prefix, source) { | ||
| const node = this._source.node(options); | ||
| const append = [this._prefix]; | ||
| return new SourceNode(null, null, null, [ | ||
| cloneAndPrefix(node, this._prefix, append) | ||
| ]); | ||
| const prefix = this._prefix; | ||
| const output = []; | ||
| const result = new SourceNode(); | ||
| node.walkSourceContents(function(source, content) { | ||
| result.setSourceContent(source, content); | ||
| }); | ||
| let needPrefix = true; | ||
| node.walk(function(chunk, mapping) { | ||
| const parts = chunk.split("\n"); | ||
| for (let i = 0; i < parts.length; i += 2) { | ||
| const nl = i + 1 < parts.length; | ||
| const part = parts[i] + (nl ? "\n" : ""); | ||
| if (part && needPrefix) { | ||
| output.push(prefix); | ||
| } | ||
| output.push( | ||
| new SourceNode( | ||
| mapping.line, | ||
| mapping.column, | ||
| mapping.source, | ||
| chunk, | ||
| mapping.name | ||
| ) | ||
| ); | ||
| needPrefix = nl; | ||
| } | ||
| }); | ||
| result.add(output); | ||
| return result; | ||
| } | ||
@@ -65,0 +69,0 @@ |
+23
-18
@@ -8,12 +8,16 @@ /* | ||
| const Source = require("./Source"); | ||
| const { | ||
| SourceNode, | ||
| SourceMapConsumer, | ||
| SourceMapGenerator | ||
| } = require("source-map"); | ||
| const { SourceNode, SourceMapConsumer } = require("source-map"); | ||
| const { SourceListMap, fromStringWithSourceMap } = require("source-list-map"); | ||
| const { getSourceAndMap, getMap } = require("./helpers"); | ||
| const applySourceMap = require("./applySourceMap"); | ||
| class SourceMapSource extends Source { | ||
| constructor(value, name, sourceMap, originalSource, innerSourceMap) { | ||
| constructor( | ||
| value, | ||
| name, | ||
| sourceMap, | ||
| originalSource, | ||
| innerSourceMap, | ||
| removeOriginalSource | ||
| ) { | ||
| super(); | ||
@@ -25,2 +29,3 @@ this._value = value; | ||
| this._innerSourceMap = innerSourceMap; | ||
| this._removeOriginalSource = removeOriginalSource; | ||
| } | ||
@@ -55,18 +60,18 @@ | ||
| node(options) { | ||
| const sourceMap = this._sourceMap; | ||
| let node = SourceNode.fromStringWithSourceMap( | ||
| this._value, | ||
| new SourceMapConsumer(sourceMap) | ||
| ); | ||
| node.setSourceContent(this._name, this._originalSource); | ||
| const innerSourceMap = this._innerSourceMap; | ||
| let sourceMap = this._sourceMap; | ||
| if (innerSourceMap) { | ||
| const sourceMapGen = SourceMapGenerator.fromSourceMap( | ||
| new SourceMapConsumer(sourceMap) | ||
| node = applySourceMap( | ||
| node, | ||
| new SourceMapConsumer(innerSourceMap), | ||
| this._name, | ||
| this._removeOriginalSource | ||
| ); | ||
| if (this._originalSource) | ||
| sourceMapGen.setSourceContent(this._name, this._originalSource); | ||
| const innerSourceMapConsumer = new SourceMapConsumer(innerSourceMap); | ||
| sourceMapGen.applySourceMap(innerSourceMapConsumer, this._name); | ||
| sourceMap = sourceMapGen.toJSON(); | ||
| } | ||
| return SourceNode.fromStringWithSourceMap( | ||
| this._value, | ||
| new SourceMapConsumer(sourceMap) | ||
| ); | ||
| return node; | ||
| } | ||
@@ -73,0 +78,0 @@ |
+1
-1
| { | ||
| "name": "webpack-sources", | ||
| "version": "2.0.0-beta.1", | ||
| "version": "2.0.0-beta.2", | ||
| "description": "Source code handling classes for webpack", | ||
@@ -5,0 +5,0 @@ "main": "./lib/index.js", |
+10
-1
@@ -105,3 +105,4 @@ # webpack-sources | ||
| originalSource?: String, | ||
| innerSourceMap?: Object | String | ||
| innerSourceMap?: Object | String, | ||
| removeOriginalSource?: boolean | ||
| ) | ||
@@ -115,3 +116,8 @@ ``` | ||
| - `innerSourceMap`: The SourceMap for the `originalSource`/`name`. | ||
| - `removeOriginalSource`: Removes the source code for `name` from the final map, keeping only the deeper mappings for that file. | ||
| The `SourceMapSource` supports "identity" mappings for the `innerSourceMap`. | ||
| When original source matches generated source for a mapping it's assumed to be mapped char by char allowing to keep finer mappings from `sourceMap`. | ||
| ## `CachedSource` | ||
@@ -161,2 +167,5 @@ | ||
| The `ReplaceSource` supports "identity" mappings for child source. | ||
| When original source matches generated source for a mapping it's assumed to be mapped char by char allowing to split mappings at replacements/insertions. | ||
| ### Public methods | ||
@@ -163,0 +172,0 @@ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
39512
18.9%15
7.14%1156
18.69%200
4.71%