Skip to content

Commit

Permalink
#18 Using the bundle url resolve origin source in jsc profiler middle…
Browse files Browse the repository at this point in the history
…ware

Reviewed By: bestander

Differential Revision: D3620292

fbshipit-source-id: e3c54fb30bc65ff1ddd650340a2905a9f0e16231
  • Loading branch information
lukaspiatkowski authored and Facebook Github Bot 8 committed Aug 2, 2016
1 parent 2231b21 commit 066de9d
Showing 1 changed file with 120 additions and 16 deletions.
136 changes: 120 additions & 16 deletions local-cli/server/middleware/jscProfilerMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,133 @@
*/
'use strict';

const SourceMapConsumer = require('../../../node_modules/source-map').SourceMapConsumer;

This comment has been minimized.

Copy link
@bestander

bestander Aug 2, 2016

Contributor

Hey Lukas, this require breaks e2e test

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') {
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);
});
});
};

0 comments on commit 066de9d

Please sign in to comment.