started support for generating source maps (WIP)
plugged in @fitzgen's source-map library
This commit is contained in:
@@ -53,7 +53,8 @@ function OutputStream(options) {
|
|||||||
width : 80,
|
width : 80,
|
||||||
max_line_len : 32000,
|
max_line_len : 32000,
|
||||||
ie_proof : true,
|
ie_proof : true,
|
||||||
beautify : true
|
beautify : true,
|
||||||
|
source_map : null
|
||||||
});
|
});
|
||||||
|
|
||||||
var indentation = 0;
|
var indentation = 0;
|
||||||
@@ -152,12 +153,12 @@ function OutputStream(options) {
|
|||||||
might_need_space = false;
|
might_need_space = false;
|
||||||
maybe_newline();
|
maybe_newline();
|
||||||
}
|
}
|
||||||
var a = str.split(/\r?\n/), n = a.length;
|
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||||
current_line += n;
|
current_line += n;
|
||||||
if (n == 1) {
|
if (n == 0) {
|
||||||
current_col += a[n - 1].length;
|
current_col += a[n].length;
|
||||||
} else {
|
} else {
|
||||||
current_col = a[n - 1].length;
|
current_col = a[n].length;
|
||||||
}
|
}
|
||||||
current_pos += str.length;
|
current_pos += str.length;
|
||||||
last = str;
|
last = str;
|
||||||
@@ -243,9 +244,22 @@ function OutputStream(options) {
|
|||||||
if (options.space_colon) space();
|
if (options.space_colon) space();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var add_mapping = options.source_map ? function(token, name) {
|
||||||
|
options.source_map.add(
|
||||||
|
current_line, current_col,
|
||||||
|
token.line, token.col,
|
||||||
|
(!name && token.type == "name") ? token.value : name
|
||||||
|
);
|
||||||
|
} : noop;
|
||||||
|
|
||||||
|
function get() {
|
||||||
|
return OUTPUT;
|
||||||
|
};
|
||||||
|
|
||||||
var stack = [];
|
var stack = [];
|
||||||
return {
|
return {
|
||||||
get : function() { return OUTPUT },
|
get : get,
|
||||||
|
toString : get,
|
||||||
indent : indent,
|
indent : indent,
|
||||||
newline : newline,
|
newline : newline,
|
||||||
print : print,
|
print : print,
|
||||||
@@ -261,6 +275,7 @@ function OutputStream(options) {
|
|||||||
with_block : with_block,
|
with_block : with_block,
|
||||||
with_parens : with_parens,
|
with_parens : with_parens,
|
||||||
with_square : with_square,
|
with_square : with_square,
|
||||||
|
add_mapping : add_mapping,
|
||||||
option : function(opt) { return options[opt] },
|
option : function(opt) { return options[opt] },
|
||||||
line : function() { return current_line },
|
line : function() { return current_line },
|
||||||
col : function() { return current_col },
|
col : function() { return current_col },
|
||||||
@@ -287,9 +302,11 @@ function OutputStream(options) {
|
|||||||
stream.push_node(self);
|
stream.push_node(self);
|
||||||
if (self.needs_parens(stream)) {
|
if (self.needs_parens(stream)) {
|
||||||
stream.with_parens(function(){
|
stream.with_parens(function(){
|
||||||
|
self.add_source_map(stream);
|
||||||
generator(self, stream);
|
generator(self, stream);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
self.add_source_map(stream);
|
||||||
generator(self, stream);
|
generator(self, stream);
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
@@ -868,11 +885,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
DEFPRINT(AST_SymbolRef, function(self, output){
|
DEFPRINT(AST_SymbolRef, function(self, output){
|
||||||
var def = self.symbol;
|
var def = self.symbol;
|
||||||
if (def) {
|
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||||
def.print(output);
|
|
||||||
} else {
|
|
||||||
output.print_name(self.name);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_This, function(self, output){
|
DEFPRINT(AST_This, function(self, output){
|
||||||
output.print("this");
|
output.print("this");
|
||||||
@@ -973,4 +986,32 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* -----[ source map generators ]----- */
|
||||||
|
|
||||||
|
function DEFMAP(nodetype, generator) {
|
||||||
|
nodetype.DEFMETHOD("add_source_map", function(stream){
|
||||||
|
generator(this, stream);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// We could easily add info for ALL nodes, but it seems to me that
|
||||||
|
// would be quite wasteful, hence this noop in the base class.
|
||||||
|
DEFMAP(AST_Node, noop);
|
||||||
|
|
||||||
|
function basic_sourcemap_gen(self, output) {
|
||||||
|
output.add_mapping(self.start);
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX: I'm not exactly sure if we need it for all of these nodes,
|
||||||
|
// or if we should add even more.
|
||||||
|
|
||||||
|
DEFMAP(AST_Directive, basic_sourcemap_gen);
|
||||||
|
DEFMAP(AST_Debugger, basic_sourcemap_gen);
|
||||||
|
DEFMAP(AST_Symbol, basic_sourcemap_gen);
|
||||||
|
DEFMAP(AST_Jump, basic_sourcemap_gen);
|
||||||
|
DEFMAP(AST_PropAccess, basic_sourcemap_gen);
|
||||||
|
DEFMAP(AST_ObjectProperty, function(self, output){
|
||||||
|
output.add_mapping(self.start, self.key);
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
77
lib/sourcemap.js
Normal file
77
lib/sourcemap.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
|
||||||
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
|
https://github.com/mishoo/UglifyJS2
|
||||||
|
|
||||||
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
|
Author: Mihai Bazon
|
||||||
|
<mihai.bazon@gmail.com>
|
||||||
|
http://mihai.bazon.net/blog
|
||||||
|
|
||||||
|
Distributed under the BSD license:
|
||||||
|
|
||||||
|
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials
|
||||||
|
provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||||
|
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
// a small wrapper around fitzgen's source-map library
|
||||||
|
function SourceMap(options) {
|
||||||
|
options = defaults(options, {
|
||||||
|
file : null,
|
||||||
|
root : null
|
||||||
|
});
|
||||||
|
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
||||||
|
file : options.file,
|
||||||
|
sourceRoot : options.root
|
||||||
|
});
|
||||||
|
var current_source = null;
|
||||||
|
function add(gen_line, gen_col, orig_line, orig_col, name) {
|
||||||
|
// AST_Node.warn("Mapping in {file}: {orig_line},{orig_col} → {gen_line},{gen_col} ({name})", {
|
||||||
|
// orig_line : orig_line,
|
||||||
|
// orig_col : orig_col,
|
||||||
|
// gen_line : gen_line,
|
||||||
|
// gen_col : gen_col,
|
||||||
|
// file : current_source,
|
||||||
|
// name : name
|
||||||
|
// });
|
||||||
|
generator.addMapping({
|
||||||
|
generated : { line: gen_line + 1, column: gen_col },
|
||||||
|
original : { line: orig_line + 1, column: orig_col },
|
||||||
|
source : current_source,
|
||||||
|
name : name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
add : add,
|
||||||
|
set_source : function(filename) { current_source = filename },
|
||||||
|
get : function() { return generator },
|
||||||
|
toString : function() { return generator.toString() }
|
||||||
|
}
|
||||||
|
};
|
||||||
39
tmp/test-maps.js
Executable file
39
tmp/test-maps.js
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
|
||||||
|
var sys = require("util");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
var UglifyJS = require("../tools/node");
|
||||||
|
|
||||||
|
var files = process.argv.slice(2);
|
||||||
|
var map = UglifyJS.SourceMap();
|
||||||
|
var output = UglifyJS.OutputStream({
|
||||||
|
beautify : false,
|
||||||
|
source_map : map
|
||||||
|
});
|
||||||
|
|
||||||
|
function do_file(file) {
|
||||||
|
var code = fs.readFileSync(file, "utf8");
|
||||||
|
|
||||||
|
// parse
|
||||||
|
var ast = UglifyJS.parse(code);
|
||||||
|
|
||||||
|
// mangle
|
||||||
|
ast.figure_out_scope();
|
||||||
|
ast.mangle_names();
|
||||||
|
|
||||||
|
// compress
|
||||||
|
var compressor = UglifyJS.Compressor();
|
||||||
|
ast.squeeze(compressor);
|
||||||
|
|
||||||
|
// generate source into the output stream
|
||||||
|
// first reset the current file name in the source map.
|
||||||
|
map.set_source(file);
|
||||||
|
ast.print(output);
|
||||||
|
};
|
||||||
|
|
||||||
|
files.forEach(do_file);
|
||||||
|
|
||||||
|
fs.writeFileSync("/tmp/source-map.json", map, "utf8");
|
||||||
|
|
||||||
|
sys.print(output);
|
||||||
@@ -4,8 +4,10 @@ var sys = require("util");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
var UglifyJS = vm.createContext({
|
var UglifyJS = vm.createContext({
|
||||||
sys : sys,
|
sys : sys,
|
||||||
console : console
|
console : console,
|
||||||
|
|
||||||
|
MOZ_SourceMap : require("source-map")
|
||||||
});
|
});
|
||||||
|
|
||||||
function load_global(file) {
|
function load_global(file) {
|
||||||
@@ -27,6 +29,7 @@ load_global("../lib/parse.js");
|
|||||||
load_global("../lib/scope.js");
|
load_global("../lib/scope.js");
|
||||||
load_global("../lib/output.js");
|
load_global("../lib/output.js");
|
||||||
load_global("../lib/compress.js");
|
load_global("../lib/compress.js");
|
||||||
|
load_global("../lib/sourcemap.js");
|
||||||
|
|
||||||
UglifyJS.AST_Node.warn_function = function(txt) {
|
UglifyJS.AST_Node.warn_function = function(txt) {
|
||||||
sys.debug(txt);
|
sys.debug(txt);
|
||||||
|
|||||||
Reference in New Issue
Block a user