* Creates a SourceNode from generated code and a SourceMapConsumer. * * @param aGeneratedCode The generated code * @param aSourceMapConsumer The SourceMap for the generated code * @param aRelativePath Optional. The path that relative sources in the * SourceMapConsumer should be
(
aGeneratedCode,
aSourceMapConsumer,
aRelativePath
)
| 53 | * SourceMapConsumer should be relative to. |
| 54 | */ |
| 55 | static fromStringWithSourceMap( |
| 56 | aGeneratedCode, |
| 57 | aSourceMapConsumer, |
| 58 | aRelativePath |
| 59 | ) { |
| 60 | // The SourceNode we want to fill with the generated code |
| 61 | // and the SourceMap |
| 62 | const node = new SourceNode(); |
| 63 | |
| 64 | // All even indices of this array are one line of the generated code, |
| 65 | // while all odd indices are the newlines between two adjacent lines |
| 66 | // (since `REGEX_NEWLINE` captures its match). |
| 67 | // Processed fragments are accessed by calling `shiftNextLine`. |
| 68 | const remainingLines = aGeneratedCode.split(REGEX_NEWLINE); |
| 69 | let remainingLinesIndex = 0; |
| 70 | const shiftNextLine = function () { |
| 71 | const lineContents = getNextLine(); |
| 72 | // The last line of a file might not have a newline. |
| 73 | const newLine = getNextLine() || ""; |
| 74 | return lineContents + newLine; |
| 75 | |
| 76 | function getNextLine() { |
| 77 | return remainingLinesIndex < remainingLines.length |
| 78 | ? remainingLines[remainingLinesIndex++] |
| 79 | : undefined; |
| 80 | } |
| 81 | }; |
| 82 | |
| 83 | // We need to remember the position of "remainingLines" |
| 84 | let lastGeneratedLine = 1, |
| 85 | lastGeneratedColumn = 0; |
| 86 | |
| 87 | // The generate SourceNodes we need a code range. |
| 88 | // To extract it current and last mapping is used. |
| 89 | // Here we store the last mapping. |
| 90 | let lastMapping = null; |
| 91 | let nextLine; |
| 92 | |
| 93 | aSourceMapConsumer.eachMapping(function (mapping) { |
| 94 | if (lastMapping !== null) { |
| 95 | // We add the code from "lastMapping" to "mapping": |
| 96 | // First check if there is a new line in between. |
| 97 | if (lastGeneratedLine < mapping.generatedLine) { |
| 98 | // Associate first line with "lastMapping" |
| 99 | addMappingWithCode(lastMapping, shiftNextLine()); |
| 100 | lastGeneratedLine++; |
| 101 | lastGeneratedColumn = 0; |
| 102 | // The remaining code is added without mapping |
| 103 | } else { |
| 104 | // There is no new line in between. |
| 105 | // Associate the code between "lastGeneratedColumn" and |
| 106 | // "mapping.generatedColumn" with "lastMapping" |
| 107 | nextLine = remainingLines[remainingLinesIndex] || ""; |
| 108 | const code = nextLine.substr( |
| 109 | 0, |
| 110 | mapping.generatedColumn - lastGeneratedColumn |
| 111 | ); |
| 112 | remainingLines[remainingLinesIndex] = nextLine.substr( |