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,
|
||||
max_line_len : 32000,
|
||||
ie_proof : true,
|
||||
beautify : true
|
||||
beautify : true,
|
||||
source_map : null
|
||||
});
|
||||
|
||||
var indentation = 0;
|
||||
@@ -152,12 +153,12 @@ function OutputStream(options) {
|
||||
might_need_space = false;
|
||||
maybe_newline();
|
||||
}
|
||||
var a = str.split(/\r?\n/), n = a.length;
|
||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||
current_line += n;
|
||||
if (n == 1) {
|
||||
current_col += a[n - 1].length;
|
||||
if (n == 0) {
|
||||
current_col += a[n].length;
|
||||
} else {
|
||||
current_col = a[n - 1].length;
|
||||
current_col = a[n].length;
|
||||
}
|
||||
current_pos += str.length;
|
||||
last = str;
|
||||
@@ -243,9 +244,22 @@ function OutputStream(options) {
|
||||
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 = [];
|
||||
return {
|
||||
get : function() { return OUTPUT },
|
||||
get : get,
|
||||
toString : get,
|
||||
indent : indent,
|
||||
newline : newline,
|
||||
print : print,
|
||||
@@ -261,6 +275,7 @@ function OutputStream(options) {
|
||||
with_block : with_block,
|
||||
with_parens : with_parens,
|
||||
with_square : with_square,
|
||||
add_mapping : add_mapping,
|
||||
option : function(opt) { return options[opt] },
|
||||
line : function() { return current_line },
|
||||
col : function() { return current_col },
|
||||
@@ -287,9 +302,11 @@ function OutputStream(options) {
|
||||
stream.push_node(self);
|
||||
if (self.needs_parens(stream)) {
|
||||
stream.with_parens(function(){
|
||||
self.add_source_map(stream);
|
||||
generator(self, stream);
|
||||
});
|
||||
} else {
|
||||
self.add_source_map(stream);
|
||||
generator(self, stream);
|
||||
}
|
||||
stream.pop_node();
|
||||
@@ -868,11 +885,7 @@ function OutputStream(options) {
|
||||
});
|
||||
DEFPRINT(AST_SymbolRef, function(self, output){
|
||||
var def = self.symbol;
|
||||
if (def) {
|
||||
def.print(output);
|
||||
} else {
|
||||
output.print_name(self.name);
|
||||
}
|
||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||
});
|
||||
DEFPRINT(AST_This, function(self, output){
|
||||
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);
|
||||
@@ -5,7 +5,9 @@ var path = require("path");
|
||||
|
||||
var UglifyJS = vm.createContext({
|
||||
sys : sys,
|
||||
console : console
|
||||
console : console,
|
||||
|
||||
MOZ_SourceMap : require("source-map")
|
||||
});
|
||||
|
||||
function load_global(file) {
|
||||
@@ -27,6 +29,7 @@ load_global("../lib/parse.js");
|
||||
load_global("../lib/scope.js");
|
||||
load_global("../lib/output.js");
|
||||
load_global("../lib/compress.js");
|
||||
load_global("../lib/sourcemap.js");
|
||||
|
||||
UglifyJS.AST_Node.warn_function = function(txt) {
|
||||
sys.debug(txt);
|
||||
|
||||
Reference in New Issue
Block a user