fix(compiler-cli): only read source-map comment from last line (#32912)
Source-maps can be linked to from a source-file by a comment at the end of the file. Previously the `SourceFileLoader` would read the first comment that matched `//# sourceMappingURL=` but this is not valid since some bundlers may include embedded source-files that contain such a comment. Now we only look for this comment in the last non-empty line in the file. PR Close #32912
This commit is contained in:
parent
dda3f49952
commit
07a07e34bc
|
@ -102,12 +102,16 @@ export class SourceFileLoader {
|
|||
* whose path is indicated in a comment or implied from the name of the source file itself.
|
||||
*/
|
||||
private loadSourceMap(sourcePath: AbsoluteFsPath, contents: string): MapAndPath|null {
|
||||
const inline = commentRegex.exec(contents);
|
||||
// Only consider a source-map comment from the last non-empty line of the file, in case there
|
||||
// are embedded source-map comments elsewhere in the file (as can be the case with bundlers like
|
||||
// webpack).
|
||||
const lastLine = this.getLastNonEmptyLine(contents);
|
||||
const inline = commentRegex.exec(lastLine);
|
||||
if (inline !== null) {
|
||||
return {map: fromComment(inline.pop()!).sourcemap, mapPath: null};
|
||||
}
|
||||
|
||||
const external = mapFileCommentRegex.exec(contents);
|
||||
const external = mapFileCommentRegex.exec(lastLine);
|
||||
if (external) {
|
||||
try {
|
||||
const fileName = external[1] || external[2];
|
||||
|
@ -175,6 +179,20 @@ export class SourceFileLoader {
|
|||
this.currentPaths.push(path);
|
||||
}
|
||||
|
||||
private getLastNonEmptyLine(contents: string): string {
|
||||
let trailingWhitespaceIndex = contents.length - 1;
|
||||
while (trailingWhitespaceIndex > 0 &&
|
||||
(contents[trailingWhitespaceIndex] === '\n' ||
|
||||
contents[trailingWhitespaceIndex] === '\r')) {
|
||||
trailingWhitespaceIndex--;
|
||||
}
|
||||
let lastRealLineIndex = contents.lastIndexOf('\n', trailingWhitespaceIndex - 1);
|
||||
if (lastRealLineIndex === -1) {
|
||||
lastRealLineIndex = 0;
|
||||
}
|
||||
return contents.substr(lastRealLineIndex + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any matched URL schemes with their corresponding path held in the schemeMap.
|
||||
*
|
||||
|
|
|
@ -63,6 +63,44 @@ runInEachFileSystem(() => {
|
|||
expect(sourceFile.rawMap).toEqual(sourceMap);
|
||||
});
|
||||
|
||||
it('should only read source-map comments from the last line of a file', () => {
|
||||
fs.ensureDir(_('/foo/src'));
|
||||
const sourceMap = createRawSourceMap({file: 'index.js'});
|
||||
fs.writeFile(_('/foo/src/external.js.map'), JSON.stringify(sourceMap));
|
||||
const sourceFile = registry.loadSourceFile(_('/foo/src/index.js'), [
|
||||
'some content',
|
||||
'//# sourceMappingURL=bad.js.map',
|
||||
'some more content',
|
||||
'//# sourceMappingURL=external.js.map',
|
||||
].join('\n'));
|
||||
if (sourceFile === null) {
|
||||
return fail('Expected source file to be defined');
|
||||
}
|
||||
expect(sourceFile.rawMap).toEqual(sourceMap);
|
||||
});
|
||||
|
||||
for (const eolMarker of ['\n', '\r\n']) {
|
||||
it(`should only read source-map comments from the last non-blank line of a file [EOL marker: ${
|
||||
eolMarker === '\n' ? '\\n' : '\\r\\n'}]`,
|
||||
() => {
|
||||
fs.ensureDir(_('/foo/src'));
|
||||
const sourceMap = createRawSourceMap({file: 'index.js'});
|
||||
fs.writeFile(_('/foo/src/external.js.map'), JSON.stringify(sourceMap));
|
||||
const sourceFile = registry.loadSourceFile(_('/foo/src/index.js'), [
|
||||
'some content',
|
||||
'//# sourceMappingURL=bad.js.map',
|
||||
'some more content',
|
||||
'//# sourceMappingURL=external.js.map',
|
||||
'',
|
||||
'',
|
||||
].join(eolMarker));
|
||||
if (sourceFile === null) {
|
||||
return fail('Expected source file to be defined');
|
||||
}
|
||||
expect(sourceFile.rawMap).toEqual(sourceMap);
|
||||
});
|
||||
}
|
||||
|
||||
it('should handle a missing external source map', () => {
|
||||
fs.ensureDir(_('/foo/src'));
|
||||
const sourceFile = registry.loadSourceFile(
|
||||
|
|
Loading…
Reference in New Issue