How to get source-mapped path to code in Browser in JavaScript?

26 views Asked by At

I have a simple error printing library which successfully retrieves the source-mapped file paths in Node.js and gets the TypeScript file paths/locations, for example. For that, basically it's this code and the @cspotcode/source-map library (that is a synchronous version of the async mozilla library, which is necessary for capturing the sync stack trace and printing on error):

import smc from '@cspotcode/source-map'
import fs from 'fs'
import pathResolve from 'path'

const SOURCE_MAP_CACHE: Record<string, smc.SourceMapConsumer> = {}

function loadSourcePath(line: string): smc.SourceMapConsumer | void {
  const link = SOURCE_MAP_CACHE[`${line}`]
  if (link) {
    return link
  }

  const fileLink = line.replace(/^file:\/\//, '')

  if (fs.existsSync(`${fileLink}.map`)) {
    const mapContent = fs.readFileSync(`${fileLink}.map`, 'utf-8')
    const json = JSON.parse(mapContent) as smc.RawSourceMap
    const sm = new smc.SourceMapConsumer(json)
    SOURCE_MAP_CACHE[`${line}`] = sm
    return sm
  }
}

function readPath(path: string, context: string): string {
  const relative = pathResolve.relative(
    process.cwd(),
    pathResolve.resolve(context, path),
  )
  return relative.startsWith('.') ? relative : `./${relative}`
}

function readHostLinkFile(
  file: string,
  line: number,
  rise: number,
): [string, number | undefined, number | undefined] {
  const link = loadSourcePath(file)

  const trace = {
    column: rise,
    filename: file,
    line: line,
  }

  if (link) {
    const token = link.originalPositionFor(trace)
    if (token.source) {
      return [
        readPath(
          token.source,
          pathResolve.dirname(file.replace(/^file:\/\//, '')),
        ),
        token.line == null ? undefined : token.line,
        token.column == null ? undefined : token.column,
      ]
    } else {
      return [file, line, rise]
    }
  } else {
    return [file, line, rise]
  }
}

How can I do this same thing in the browser? My errors currently link to the compiled JS output, like this, even though there is the //# sourceMappingURL at the bottom of the file.

enter image description here

What do I need to do to map .js paths with line:column numbers (such as from an error stack trace) to go to the TypeScript file through source maps, in the browser? Do I like need to:

  1. Fetch the .js file with await fetch(url).
  2. And parse the //# sourceMappingURL data-uri somehow?

Or is there a different way? Or any libraries for this? Looked around a bit but found almost nothing. That sourcemap library for node.js depends on the fs, so probably won't work there.

0

There are 0 answers