Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply source maps to profiles #50894

Open
mbrevda opened this issue Nov 24, 2023 · 4 comments
Open

Apply source maps to profiles #50894

mbrevda opened this issue Nov 24, 2023 · 4 comments
Labels
feature request Issues that request new features to be added to Node.js. source maps Issues and PRs related to source map support.

Comments

@mbrevda
Copy link

mbrevda commented Nov 24, 2023

What is the problem this feature will solve?

When debugging bundled/compiled/minified code, it's difficult to read a profile as locations and many function names point to the compiled code.

What is the feature you are proposing to solve the problem?

Apply source maps to profiles (perhaps when --enable-source-maps is passed).

What alternatives have you considered?

post-augmentation (via the source-map package), or other tools (such as speedscope) which claim to be able to apply sourcemaps (but dont always work).

@mbrevda mbrevda added the feature request Issues that request new features to be added to Node.js. label Nov 24, 2023
Copy link
Contributor

There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-stale Mark issue so that it is never considered stale label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot added the stale label May 23, 2024
@mbrevda
Copy link
Author

mbrevda commented May 23, 2024

maintainers: can we get some sort of signal here so that this issue doesn't stay open unnecessarily?

@github-actions github-actions bot removed the stale label May 24, 2024
@brunoargolo
Copy link

@mbrevda, I'm having similar a issue did you find any workarounds or post augmentation tools for this?

@RedYetiDev RedYetiDev added the source maps Issues and PRs related to source map support. label Jul 9, 2024
@mbrevda
Copy link
Author

mbrevda commented Jul 10, 2024

Here's a script I'm using to augment post profile
import {readFile} from 'fs/promises';
import {SourceMapConsumer} from 'source-map';
import {join} from 'path';

const sourceMap = {};
const loadSourceMap = async (codePath, filepath) => {
  const sourceFile = await readFile(codePath + '/' + filepath, 'utf-8');
  const mapFileUrlLine = sourceFile
    .split('\n')
    .reverse()
    .find((line) => line.startsWith('//# sourceMappingURL='));

  if (!mapFileUrlLine) {
    console.warning('could not find sourceMappingURL line for', filepath);
    return false;
  }

  const mapFileUrl = mapFileUrlLine.replace('//# sourceMappingURL=', '');
  const mapFile = await readFile(codePath + '/' + mapFileUrl, 'utf-8');
  if (!mapFile) {
    console.warning(`could not find source map file ${mapFile} for`, filepath);
    return false;
  }
  return await new SourceMapConsumer(mapFile);
};

const remapProfile = async (projectDir, trace) => {
  const codePath = projectDir + '/dist';

  const mappedNodes = [];
  for (const [index, node] of trace.nodes.entries()) {
    mappedNodes.push(node);
    const {url, lineNumber, columnNumber, functionName} = node.callFrame;
    if (!url || !lineNumber) continue;

    const {protocol, pathname} = new URL(url);
    if (!pathname.startsWith(codePath)) continue;
    const filepath = pathname.replace(codePath + '/', '');

    if (sourceMap[filepath] === false) continue; // we already tried to load this source map and failed
    if (!(filepath in sourceMap)) {
      sourceMap[filepath] = await loadSourceMap(codePath, filepath);
    }
    if (!sourceMap[filepath]) continue;

    const {source, line, column, name} = sourceMap[
      filepath
    ].originalPositionFor({
      line: lineNumber,
      column: columnNumber,
    });
    if (!source && !line && !column && !name) continue;

    const mappedUrl = source ? `${protocol}//` + join(codePath, source) : url;

    // use original function name if available
    let mappedFunctionName = functionName;
    if (name) {
      // if we have a name, but no function name, use the name
      if (!functionName) {
        mappedFunctionName = name;
      } else {
        // if we have both, use both
        mappedFunctionName = `${name} (${functionName})`;
      }
    }

    mappedNodes[index] = {
      ...mappedNodes[index],
      callFrame: {
        ...(mappedNodes[index]?.callFrame || {}),
        url: mappedUrl,
        lineNumber: line,
        columnNumber: column,
        functionName: mappedFunctionName,
      },
    };
  }
  return {...trace, nodes: mappedNodes};
};

export default async (projectDir, profile) => {
  return await remapProfile(projectDir, profile);
};

</details>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. source maps Issues and PRs related to source map support.
Projects
Development

No branches or pull requests

3 participants