aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/eliminator/node_modules/uglify-js/lib/process.js34
-rwxr-xr-xtools/source-maps/sourcemapper.js106
2 files changed, 106 insertions, 34 deletions
diff --git a/tools/eliminator/node_modules/uglify-js/lib/process.js b/tools/eliminator/node_modules/uglify-js/lib/process.js
index 660001aa..39ccde37 100644
--- a/tools/eliminator/node_modules/uglify-js/lib/process.js
+++ b/tools/eliminator/node_modules/uglify-js/lib/process.js
@@ -65,6 +65,7 @@ function NodeWithLine(str, line) {
NodeWithLine.prototype = new String();
NodeWithLine.prototype.toString = function() { return this.str; }
+NodeWithLine.prototype.valueOf = function() { return this.str; }
NodeWithLine.prototype.lineComment = function() { return " // @line " + this.line; }
// XXX ugly hack
@@ -473,7 +474,10 @@ function gen_code(ast, options) {
a.push(m[2] + "e-" + (m[1].length + m[2].length),
str.substr(str.indexOf(".")));
}
- return best_of(a);
+ var best = best_of(a);
+ if (options.debug && this[0].start)
+ return new NodeWithLine(best, this[0].start.line);
+ return best;
};
var w = ast_walker();
@@ -499,7 +503,16 @@ function gen_code(ast, options) {
},
"block": make_block,
"var": function(defs) {
- return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
+ var s = "var " + add_commas(MAP(defs, make_1vardef)) + ";";
+ if (options.debug) {
+ // hack: we don't support mapping one optimized line to more than one
+ // generated line, so in case of multiple comma-separated var definitions,
+ // just take the first
+ if (defs[0][1] && defs[0][1][0] && defs[0][1][0].start) {
+ return s + (new NodeWithLine(s, defs[0][1][0].start.line)).lineComment();
+ }
+ }
+ return s;
},
"const": function(defs) {
return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
@@ -555,8 +568,8 @@ function gen_code(ast, options) {
if (op && op !== true) op += "=";
else op = "=";
var s = add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]);
- if (options.debug && lvalue[0].start)
- return new NodeWithLine(s, lvalue[0].start.line);
+ if (options.debug && this[0].start)
+ return new NodeWithLine(s, this[0].start.line);
return s;
},
"dot": function(expr) {
@@ -574,9 +587,12 @@ function gen_code(ast, options) {
var f = make(func);
if (needs_parens(func))
f = "(" + f + ")";
- return f + "(" + add_commas(MAP(args, function(expr){
+ var str = f + "(" + add_commas(MAP(args, function(expr){
return parenthesize(expr, "seq");
})) + ")";
+ if (options.debug && this[0].start)
+ return new NodeWithLine(str, this[0].start.line)
+ return str;
},
"function": make_function,
"defun": make_function,
@@ -613,7 +629,7 @@ function gen_code(ast, options) {
var out = [ "return" ];
var str = make(expr);
if (expr != null) out.push(str);
- return add_spaces(out) + ";" + str.lineComment();
+ return add_spaces(out) + ";" + (str ? str.lineComment() : '');
},
"binary": function(operator, lvalue, rvalue) {
var left = make(lvalue), right = make(rvalue);
@@ -633,7 +649,11 @@ function gen_code(ast, options) {
&& rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) {
right = " " + right;
}
- return add_spaces([ left, operator, right ]);
+ var tok = this[0];
+ var str = add_spaces([ left, operator, right ]);
+ if (options.debug && tok.start)
+ return new NodeWithLine(str, tok.start.line);
+ return str;
},
"unary-prefix": function(operator, expr) {
var val = make(expr);
diff --git a/tools/source-maps/sourcemapper.js b/tools/source-maps/sourcemapper.js
index c7021a0f..ba993aa1 100755
--- a/tools/source-maps/sourcemapper.js
+++ b/tools/source-maps/sourcemapper.js
@@ -2,6 +2,9 @@
"use strict";
+var fs = require('fs');
+var path = require('path');
+
function countLines(s) {
var count = 0;
for (var i = 0, l = s.length; i < l; i ++) {
@@ -63,21 +66,39 @@ function extractComments(source, commentHandler) {
}
}
-function generateMap(fileName, sourceRoot, mapFileBaseName, generatedLineOffset) {
- var fs = require('fs');
- var path = require('path');
+function getMappings(source) {
+ // generatedLineNumber -> { originalLineNumber, originalFileName }
+ var mappings = {};
+ extractComments(source, function(content, generatedLineNumber) {
+ var matches = /@line (\d+)(?: "([^"]*)")?/.exec(content);
+ if (matches === null) return;
+ var originalFileName = matches[2];
+ mappings[generatedLineNumber] = {
+ originalLineNumber: parseInt(matches[1], 10),
+ originalFileName: originalFileName
+ }
+ });
+ return mappings;
+}
+
+function generateMap(mappings, sourceRoot, mapFileBaseName, generatedLineOffset) {
var SourceMapGenerator = require('source-map').SourceMapGenerator;
var generator = new SourceMapGenerator({ file: mapFileBaseName });
- var generatedSource = fs.readFileSync(fileName, 'utf-8');
var seenFiles = Object.create(null);
- extractComments(generatedSource, function(content, generatedLineNumber) {
- var matches = /@line (\d+) "([^"]*)"/.exec(content);
- if (matches === null) return;
- var originalLineNumber = parseInt(matches[1], 10);
- var originalFileName = matches[2];
+ for (var generatedLineNumber in mappings) {
+ var generatedLineNumber = parseInt(generatedLineNumber, 10);
+ var mapping = mappings[generatedLineNumber];
+ var originalFileName = mapping.originalFileName;
+ generator.addMapping({
+ generated: { line: generatedLineNumber + generatedLineOffset, column: 0 },
+ original: { line: mapping.originalLineNumber, column: 0 },
+ source: originalFileName
+ });
+ // we could call setSourceContent repeatedly, but readFileSync is slow, so
+ // avoid doing it unnecessarily
if (!(originalFileName in seenFiles)) {
seenFiles[originalFileName] = true;
var rootedPath = originalFileName[0] === path.sep ?
@@ -89,33 +110,64 @@ function generateMap(fileName, sourceRoot, mapFileBaseName, generatedLineOffset)
" at " + rootedPath);
}
}
+ }
- generator.addMapping({
- generated: { line: generatedLineNumber + generatedLineOffset, column: 0 },
- original: { line: originalLineNumber, column: 0 },
- source: originalFileName
- });
- });
-
- var mapFileName = mapFileBaseName + '.map';
- fs.writeFileSync(mapFileName, generator.toString());
+ fs.writeFileSync(mapFileBaseName + '.map', generator.toString());
+}
- var lastLine = generatedSource.slice(generatedSource.lastIndexOf('\n'));
+function appendMappingURL(fileName, source, mapFileName) {
+ var lastLine = source.slice(source.lastIndexOf('\n'));
if (!/sourceMappingURL/.test(lastLine))
fs.appendFileSync(fileName, '//@ sourceMappingURL=' + path.basename(mapFileName));
}
+function parseArgs(args) {
+ var rv = { _: [] }; // unflagged args go into `_`; similar to the optimist library
+ for (var i = 0; i < args.length; i++) {
+ if (/^--/.test(args[i])) rv[args[i].slice(2)] = args[++i];
+ else rv._.push(args[i]);
+ }
+ return rv;
+}
+
if (require.main === module) {
if (process.argv.length < 3) {
- console.log('Usage: ./sourcemapper.js <filename> <source root (default: .)> ' +
- '<map file basename (default: filename)>' +
- '<generated line offset (default: 0)>');
+ console.log('Usage: ./sourcemapper.js <original js> <optimized js file ...> \\\n' +
+ '\t--sourceRoot <default "."> \\\n' +
+ '\t--mapFileBaseName <default `filename`> \\\n' +
+ '\t--offset <default 0>');
process.exit(1);
} else {
- var sourceRoot = process.argv.length > 3 ? process.argv[3] : ".";
- var mapFileBaseName = process.argv.length > 4 ? process.argv[4] : process.argv[2];
- var generatedLineOffset = process.argv.length > 5 ?
- parseInt(process.argv[5], 10) : 0;
- generateMap(process.argv[2], sourceRoot, mapFileBaseName, generatedLineOffset);
+ var opts = parseArgs(process.argv.slice(2));
+ var fileName = opts._[0];
+ var sourceRoot = opts.sourceRoot ? opts.sourceRoot : ".";
+ var mapFileBaseName = opts.mapFileBaseName ? opts.mapFileBaseName : fileName;
+ var generatedLineOffset = opts.offset ? parseInt(opts.offset, 10) : 0;
+
+ var generatedSource = fs.readFileSync(fileName, 'utf-8');
+ var source = generatedSource;
+ var mappings = getMappings(generatedSource);
+ for (var i = 1, l = opts._.length; i < l; i ++) {
+ var optimizedSource = fs.readFileSync(opts._[i], 'utf-8')
+ var optimizedMappings = getMappings(optimizedSource);
+ var newMappings = {};
+ // uglify processes the code between EMSCRIPTEN_START_FUNCS and
+ // EMSCRIPTEN_END_FUNCS, so its line number maps are relative to those
+ // markers. we correct for that here.
+ var startFuncsLineNumber = countLines(
+ source.slice(0, source.indexOf('// EMSCRIPTEN_START_FUNCS'))) + 2;
+ for (var line in optimizedMappings) {
+ var originalLineNumber = optimizedMappings[line].originalLineNumber + startFuncsLineNumber;
+ if (originalLineNumber in mappings) {
+ newMappings[line] = mappings[originalLineNumber];
+ }
+ }
+ mappings = newMappings;
+ source = optimizedSource;
+ }
+
+ generateMap(mappings, sourceRoot, mapFileBaseName, generatedLineOffset);
+ appendMappingURL(opts._[opts._.length - 1], generatedSource,
+ opts.mapFileBaseName + '.map');
}
}