/** * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import { RawSourceMap, SourceMapConsumer } from 'source-map'; /** * A wrapped instance of a {@link https://github.com/mozilla/source-map SourceMapConsumer}. * * This exposes methods which will be indifferent to changes made in {@link https://github.com/mozilla/source-map source-map}. */ export class SourceMap { __source_map: SourceMapConsumer; constructor(sourceMap: SourceMapConsumer) { this.__source_map = sourceMap; } /** * Returns the original code position for a generated code position. * @param {number} line The line of the generated code position. * @param {number} column The column of the generated code position. */ getOriginalPosition( line: number, column: number, ): { source: string | null; line: number | null; column: number | null } { const { line: l, column: c, source: s, } = this.__source_map.originalPositionFor({ line, column, }); return { line: l, column: c, source: s }; } /** * Returns the generated code position for an original position. * @param {string} source The source file of the original code position. * @param {number} line The line of the original code position. * @param {number} column The column of the original code position. */ getGeneratedPosition( source: string, line: number, column: number, ): { line: number | null; column: number | null } { const { line: l, column: c } = this.__source_map.generatedPositionFor({ source, line, column, }); return { line: l, column: c, }; } /** * Returns the code for a given source file name. * @param {string} sourceName The name of the source file. */ getSource(sourceName: string): string | null { return this.__source_map.sourceContentFor(sourceName); } getSources(): string[] { return (this.__source_map as unknown as { sources: string[] }).sources; } } export function extractSourceMapUrl( fileUri: string, fileContents: string, ): Promise { const regex = /\/\/[#@] ?sourceMappingURL=([^\s'"]+)\s*$/gm; let match = null; for (;;) { const next = regex.exec(fileContents); if (next == null) { break; } match = next; } if (!(match && match[1])) { return Promise.reject( new Error(`Cannot find a source map directive for ${fileUri}.`), ); } return Promise.resolve(match[1].toString()); } /** * Returns an instance of {@link SourceMap} for a given fileUri and fileContents. * @param {string} fileUri The URI of the source file. * @param {string} fileContents The contents of the source file. */ export async function getSourceMap( //function getSourceMap( fileUri: string, fileContents: string, ): Promise { let sm = await extractSourceMapUrl(fileUri, fileContents); if (sm.indexOf('data:') === 0) { const base64 = /^data:application\/json;([\w=:"-]+;)*base64,/; const match2 = base64.exec(sm); if (!match2) { throw new Error( 'Sorry, non-base64 inline source-map encoding is not supported.', ); } sm = sm.substring(match2[0].length); sm = window.atob(sm); sm = JSON.parse(sm); return new SourceMap(new SourceMapConsumer(sm as unknown as RawSourceMap)); } else { const index = fileUri.lastIndexOf('/'); const url = fileUri.substring(0, index + 1) + sm; const obj = await fetch(url).then((res) => res.json()); return new SourceMap(new SourceMapConsumer(obj as RawSourceMap)); } /* return extractSourceMapUrl(fileUri, fileContents) .then(sm => { if (sm.indexOf('data:') === 0) { const base64 = /^data:application\/json;([\w=:"-]+;)*base64,/; const match2 = sm.match(base64); if (!match2) { throw new Error( 'Sorry, non-base64 inline source-map encoding is not supported.' ); } sm = sm.substring(match2[0].length); sm = window.atob(sm); sm = JSON.parse(sm); return new SourceMap(new SourceMapConsumer(sm)); } else { const index = fileUri.lastIndexOf('/'); const url = fileUri.substring(0, index + 1) + sm; return fetch(url).then(res => res.json()) .then(obj => { return new SourceMap(new SourceMapConsumer(obj)) }) //const obj = await fetch(url).then(res => res.json()); //return new SourceMap(new SourceMapConsumer(obj)); } }); */ } export default getSourceMap;