#18 Using the bundle url resolve origin source in jsc profiler middleware
Reviewed By: bestander Differential Revision: D3620292 fbshipit-source-id: e3c54fb30bc65ff1ddd650340a2905a9f0e16231
This commit is contained in:
parent
2231b21ed0
commit
066de9d820
|
@ -8,7 +8,104 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
const SourceMapConsumer = require('../../../node_modules/source-map').SourceMapConsumer;
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const urlLib = require('url');
|
||||
|
||||
class TreeTransformator {
|
||||
constructor() {
|
||||
this.urlResults = {};
|
||||
}
|
||||
|
||||
transform(tree, callback) {
|
||||
this.afterUrlsCacheBuild(tree, () => {
|
||||
callback(this.transformNode(tree));
|
||||
});
|
||||
}
|
||||
|
||||
// private
|
||||
transformNode(tree) {
|
||||
if (tree.url in this.urlResults) {
|
||||
const original = this.urlResults[tree.url].originalPositionFor({
|
||||
line: tree.lineNumber,
|
||||
column: tree.columnNumber,
|
||||
});
|
||||
tree.scriptId = tree.id;
|
||||
tree.url = 'file://' + original.source;
|
||||
tree.lineNumber = original.line;
|
||||
tree.columnNumber = original.column;
|
||||
}
|
||||
tree.children = tree.children.map((t) => this.transformNode(t));
|
||||
return tree;
|
||||
}
|
||||
|
||||
// private
|
||||
afterUrlsCacheBuild(tree, callback) {
|
||||
let urls = new Set();
|
||||
this.gatherUrls(tree, urls);
|
||||
|
||||
let size = urls.size;
|
||||
if (size === 0) {
|
||||
callback();
|
||||
} else {
|
||||
urls.forEach((url) => {
|
||||
this.callUrlCached(url, () => {
|
||||
--size;
|
||||
if (size === 0) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// private
|
||||
gatherUrls(tree, urls) {
|
||||
urls.add(tree.url);
|
||||
tree.children.map((t) => this.gatherUrls(t, urls));
|
||||
}
|
||||
|
||||
// private
|
||||
callUrlCached(url, callback) {
|
||||
if (url === '' || url === null || url in this.urlResults) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedUrl = urlLib.parse(url);
|
||||
const options = {
|
||||
host: parsedUrl.hostname,
|
||||
port: parsedUrl.port,
|
||||
path: parsedUrl.pathname.replace(/\.bundle$/, '.map') + parsedUrl.search,
|
||||
};
|
||||
|
||||
http.get(options, (res) => {
|
||||
res.setEncoding('utf8');
|
||||
let sawEnd = false;
|
||||
let resBody = '';
|
||||
res.on('data', (chunk) => {
|
||||
resBody += chunk;
|
||||
}).on('end', () => {
|
||||
sawEnd = true;
|
||||
const map = JSON.parse(resBody.replace(/^\)\]\}'/, ''));
|
||||
this.urlResults[url] = new SourceMapConsumer(map);
|
||||
callback();
|
||||
}).on('close', (err) => {
|
||||
if (!sawEnd) {
|
||||
console.error('Connection terminated prematurely because of: '
|
||||
+ err.code + ' for url: ' + url);
|
||||
this.urlResults[url] = null;
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}).on('error', (err) => {
|
||||
console.error('Could not get response from: ' + url);
|
||||
this.urlResults[url] = null;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function(req, res, next) {
|
||||
if (req.url !== '/jsc-profile') {
|
||||
|
@ -16,21 +113,28 @@ module.exports = function(req, res, next) {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log('Dumping JSC profile information...');
|
||||
const dumpName = '/tmp/jsc-profile_' + Date.now() + '.cpuprofile';
|
||||
fs.writeFile(dumpName, req.rawBody, (err) => {
|
||||
var response = '';
|
||||
if (err) {
|
||||
response =
|
||||
'An error occured when trying to save the profile at ' + dumpName;
|
||||
console.error(response, err);
|
||||
} else {
|
||||
response =
|
||||
'Your profile was generated at\n\n' + dumpName + '\n\n' +
|
||||
'Open `Chrome Dev Tools > Profiles > Load` '
|
||||
+ 'and select the profile to visualize it.';
|
||||
console.log(response);
|
||||
}
|
||||
res.end(response);
|
||||
console.log('Received request from JSC profiler, post processing it...');
|
||||
let profile = JSON.parse(req.rawBody);
|
||||
(new TreeTransformator()).transform(profile.head, (newHead) => {
|
||||
profile.head = newHead;
|
||||
|
||||
console.log('Dumping JSC profile information...');
|
||||
const dumpName = '/tmp/jsc-profile_' + Date.now() + '.cpuprofile';
|
||||
|
||||
fs.writeFile(dumpName, JSON.stringify(profile), (err) => {
|
||||
let response = '';
|
||||
if (err) {
|
||||
response =
|
||||
'An error occured when trying to save the profile at ' + dumpName;
|
||||
console.error(response, err);
|
||||
} else {
|
||||
response =
|
||||
'Your profile was generated at\n\n' + dumpName + '\n\n' +
|
||||
'Open `Chrome/Atom Dev Tools > Profiles > Load` '
|
||||
+ 'and select the profile to visualize it.';
|
||||
console.log(response);
|
||||
}
|
||||
res.end(response);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue