Compare commits

...

11 Commits

Author SHA1 Message Date
Mihai Bazon
d558abbdb7 v2.4.21 2015-05-04 19:14:42 +03:00
Mihai Bazon
4aed0830e5 Fix blank lines in the output.
The issue was more obvious when max_line_len has a small value, rather than
the default 32K characters.  A blank line showed up after most statements.
2015-05-04 17:55:42 +03:00
Mihai Bazon
d2dda34b2a Remove deprecated calls to utils.print/utils.error
Close #542, #641, #647
2015-05-04 15:07:16 +03:00
Mihai Bazon
c3a10c135e Avoid spurious brackets when dropping unused vars
Fix #702
2015-05-04 14:49:17 +03:00
Mihai Bazon
92e4340732 Fix parsing strings with literal DOS newlines
(should not set newline_before)

Fix #693
2015-04-23 12:08:19 +03:00
Mihai Bazon
7b22f2031f If name_cache is specified, do rename cached properties
(even if --mangle-props is not there)
2015-04-22 17:34:49 +03:00
Mihai Bazon
3b14582d6b Fix tests 2015-04-17 11:28:59 +03:00
Mihai Bazon
274e1b3dc7 Drop NaN -> 0/0 transformation.
Fix #687
2015-04-17 11:26:36 +03:00
Fábio Santos
de58b0289d Added expect_exact for testing the OutputStream
This works almost exactly like `expect`, except that you pass a literal string
of which the result is compared with the generated output.
2015-04-14 20:26:47 +02:00
XhmikosR
efea52a4f4 Normalize package.json.
* Specify the files to install in package.json
* Add missing properties
* Follow `npm init`'s scheme
2015-04-14 20:17:03 +02:00
Jordan Harband
763bd36b60 Test on latest node and io.js
Per 0262b4244c - if you're going to stop testing on 0.8, you should be testing on 0.12.

Also allow failures on unstable nodes and "older than two latest" `io.js` versions, and enable "sudo: false" which makes tests run faster.
2015-04-14 20:06:09 +02:00
12 changed files with 123 additions and 84 deletions

3
.gitignore vendored
View File

@@ -1,2 +1,3 @@
/node_modules/
/npm-debug.log
tmp/
node_modules/

View File

@@ -1,2 +0,0 @@
test
.travis.yml

View File

@@ -1,5 +1,10 @@
language: node_js
before_install: "npm install -g npm"
node_js:
- "0.10"
- "iojs"
- "0.12"
- "0.11"
- "0.10"
matrix:
fast_finish: true
sudo: false

View File

@@ -132,24 +132,24 @@ normalize(ARGS);
if (ARGS.noerr) {
UglifyJS.DefaultsError.croak = function(msg, defs) {
sys.error("WARN: " + msg);
print_error("WARN: " + msg);
};
}
if (ARGS.version || ARGS.V) {
var json = require("../package.json");
sys.puts(json.name + ' ' + json.version);
print(json.name + ' ' + json.version);
process.exit(0);
}
if (ARGS.ast_help) {
var desc = UglifyJS.describe_ast();
sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
print(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
process.exit(0);
}
if (ARGS.h || ARGS.help) {
sys.puts(yargs.help());
print(yargs.help());
process.exit(0);
}
@@ -221,7 +221,7 @@ if (ARGS.comments != null) {
try {
OUTPUT_OPTIONS.comments = new RegExp(ARGS.comments.substr(1, regex_pos - 1), ARGS.comments.substr(regex_pos + 1));
} catch (e) {
sys.error("ERROR: Invalid --comments: " + e.message);
print_error("ERROR: Invalid --comments: " + e.message);
}
} else if (ARGS.comments == "all") {
OUTPUT_OPTIONS.comments = true;
@@ -241,7 +241,7 @@ var files = ARGS._.slice();
if (ARGS.self) {
if (files.length > 0) {
sys.error("WARN: Ignoring input files since --self was passed");
print_error("WARN: Ignoring input files since --self was passed");
}
files = UglifyJS.FILES;
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
@@ -253,7 +253,7 @@ var ORIG_MAP = ARGS.in_source_map;
if (ORIG_MAP) {
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
if (files.length == 0) {
sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file);
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
files = [ ORIG_MAP.file ];
}
if (ARGS.source_map_root == null) {
@@ -266,12 +266,12 @@ if (files.length == 0) {
}
if (files.indexOf("-") >= 0 && ARGS.source_map) {
sys.error("ERROR: Source map doesn't work with input from STDIN");
print_error("ERROR: Source map doesn't work with input from STDIN");
process.exit(1);
}
if (files.filter(function(el){ return el == "-" }).length > 1) {
sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
print_error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
process.exit(1);
}
@@ -294,9 +294,9 @@ try {
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
} catch(ex) {
if (ex instanceof UglifyJS.DefaultsError) {
sys.error(ex.msg);
sys.error("Supported options:");
sys.error(sys.inspect(ex.defs));
print_error(ex.msg);
print_error("Supported options:");
print_error(sys.inspect(ex.defs));
process.exit(1);
}
}
@@ -304,7 +304,7 @@ try {
async.eachLimit(files, 1, function (file, cb) {
read_whole_file(file, function (err, code) {
if (err) {
sys.error("ERROR: can't read file: " + file);
print_error("ERROR: can't read file: " + file);
process.exit(1);
}
if (ARGS.p != null) {
@@ -341,9 +341,9 @@ async.eachLimit(files, 1, function (file, cb) {
});
} catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) {
sys.error("Parse error at " + file + ":" + ex.line + "," + ex.col);
sys.error(ex.message);
sys.error(ex.stack);
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
print_error(ex.message);
print_error(ex.stack);
process.exit(1);
}
throw ex;
@@ -372,12 +372,13 @@ async.eachLimit(files, 1, function (file, cb) {
TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
}
if (ARGS.mangle_props) (function(){
if (ARGS.mangle_props || ARGS.name_cache) (function(){
var reserved = RESERVED ? RESERVED.props : null;
var cache = readNameCache("props");
TOPLEVEL = UglifyJS.mangle_properties(TOPLEVEL, {
reserved: reserved,
cache: cache
reserved : reserved,
cache : cache,
only_cache : !ARGS.mangle_props
});
writeNameCache("props", cache);
})();
@@ -443,15 +444,15 @@ async.eachLimit(files, 1, function (file, cb) {
if (OUTPUT_FILE) {
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
} else {
sys.print(output);
print(output);
}
if (ARGS.stats) {
sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", {
print_error(UglifyJS.string_template("Timing information (compressed {count} files):", {
count: files.length
}));
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
sys.error(UglifyJS.string_template("- {name}: {time}s", {
print_error(UglifyJS.string_template("- {name}: {time}s", {
name: i,
time: (STATS[i] / 1000).toFixed(3)
}));
@@ -478,7 +479,7 @@ function getOptions(x, constants) {
ast = UglifyJS.parse(x, { expression: true });
} catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) {
sys.error("Error parsing arguments in: " + x);
print_error("Error parsing arguments in: " + x);
process.exit(1);
}
}
@@ -497,8 +498,8 @@ function getOptions(x, constants) {
ret[name] = true;
return true; // no descend
}
sys.error(node.TYPE)
sys.error("Error parsing arguments in: " + x);
print_error(node.TYPE)
print_error("Error parsing arguments in: " + x);
process.exit(1);
}));
}
@@ -530,3 +531,11 @@ function time_it(name, cont) {
}
return ret;
}
function print_error(msg) {
console.error("%s", msg);
}
function print(txt) {
console.log("%s", txt);
}

View File

@@ -1168,12 +1168,12 @@ merge(Compressor.prototype, {
return make_node(AST_EmptyStatement, node);
}
if (def.length == 0) {
return side_effects;
return in_list ? MAP.splice(side_effects.body) : side_effects;
}
node.definitions = def;
if (side_effects) {
side_effects.body.unshift(node);
node = side_effects;
return in_list ? MAP.splice(side_effects.body) : side_effects;
}
return node;
}
@@ -2272,14 +2272,6 @@ merge(Compressor.prototype, {
});
});
OPT(AST_NaN, function (self, compressor) {
return make_node(AST_Binary, self, {
operator : '/',
left : make_node(AST_Number, self, {value: 0}),
right : make_node(AST_Number, self, {value: 0})
});
});
OPT(AST_Undefined, function(self, compressor){
if (compressor.option("unsafe")) {
var scope = compressor.find_parent(AST_Scope);

View File

@@ -176,7 +176,6 @@ function OutputStream(options) {
might_need_space = false;
}
might_need_semicolon = false;
maybe_newline();
}
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {

View File

@@ -354,8 +354,13 @@ function tokenizer($TEXT, filename, html5_comments) {
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
case 117 : return String.fromCharCode(hex_bytes(4)); // \u
case 10 : return ""; // newline
default : return ch;
case 13 : // \r
if (peek() == "\n") { // DOS newline
next(true, in_string);
return "";
}
}
return ch;
};
function hex_bytes(n) {
@@ -372,7 +377,7 @@ function tokenizer($TEXT, filename, html5_comments) {
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
var quote = next(), ret = "";
for (;;) {
var ch = next(true);
var ch = next(true, true);
if (ch == "\\") {
// read OctalEscapeSequence (XXX: deprecated if "strict mode")
// https://github.com/mishoo/UglifyJS/issues/178

View File

@@ -63,7 +63,8 @@ function find_builtins() {
function mangle_properties(ast, options) {
options = defaults(options, {
reserved : null,
cache : null
cache : null,
only_cache : false
});
var reserved = options.reserved;
@@ -139,6 +140,9 @@ function mangle_properties(ast, options) {
// only function declarations after this line
function can_mangle(name) {
if (options.only_cache) {
return cache.props.has(name);
}
if (reserved.indexOf(name) >= 0) return false;
if (/^[0-9.]+$/.test(name)) return false;
return true;

View File

@@ -1,37 +1,51 @@
{
"name": "uglify-js",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"main": "tools/node.js",
"version": "2.4.20",
"engines": { "node" : ">=0.4.0" },
"maintainers": [{
"name": "Mihai Bazon",
"email": "mihai.bazon@gmail.com",
"web": "http://lisperator.net/"
}],
"repository": {
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"dependencies": {
"async" : "~0.2.6",
"source-map" : "0.1.34",
"yargs": "~3.5.4",
"uglify-to-browserify": "~1.0.0"
},
"devDependencies": {
"acorn": "~0.6.0",
"escodegen": "~1.3.3",
"esfuzz": "~0.3.1",
"estraverse": "~1.5.1"
},
"browserify": {
"transform": [ "uglify-to-browserify" ]
},
"bin": {
"uglifyjs" : "bin/uglifyjs"
},
"license": "BSD",
"scripts": {"test": "node test/run-tests.js"}
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD",
"version": "2.4.21",
"engines": {
"node": ">=0.4.0"
},
"maintainers": [
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
],
"repository": {
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"bugs": {
"url": "https://github.com/mishoo/UglifyJS2/issues"
},
"main": "tools/node.js",
"bin": {
"uglifyjs": "bin/uglifyjs"
},
"files": [
"bin",
"lib",
"tools",
"LICENSE"
],
"dependencies": {
"async": "~0.2.6",
"source-map": "0.1.34",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.5.4"
},
"devDependencies": {
"acorn": "~0.6.0",
"escodegen": "~1.3.3",
"esfuzz": "~0.3.1",
"estraverse": "~1.5.1"
},
"browserify": {
"transform": [
"uglify-to-browserify"
]
},
"scripts": {
"test": "node test/run-tests.js"
}
}

View File

@@ -6,7 +6,7 @@ NaN_and_Infinity_must_have_parens: {
}
expect: {
(1/0).toString();
(0/0).toString();
NaN.toString(); // transformation to 0/0 dropped
}
}

View File

@@ -84,7 +84,12 @@ function run_compress_tests() {
warnings: false
});
var cmp = new U.Compressor(options, true);
var expect = make_code(as_toplevel(test.expect), false);
var expect;
if (test.expect) {
expect = make_code(as_toplevel(test.expect), false);
} else {
expect = test.expect_exact;
}
var input = as_toplevel(test.input);
var input_code = make_code(test.input);
var output = input.transform(cmp);
@@ -150,7 +155,7 @@ function parse_test(file) {
}
if (node instanceof U.AST_LabeledStatement) {
assert.ok(
node.label.name == "input" || node.label.name == "expect",
node.label.name == "input" || node.label.name == "expect" || node.label.name == "expect_exact",
tmpl("Unsupported label {name} [{line},{col}]", {
name: node.label.name,
line: node.label.start.line,
@@ -162,7 +167,16 @@ function parse_test(file) {
if (stat.body.length == 1) stat = stat.body[0];
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
}
test[node.label.name] = stat;
if (node.label.name === "expect_exact") {
if (!(stat.TYPE === "SimpleStatement" && stat.body.TYPE === "String")) {
throw new Error(
"The value of the expect_exact clause should be a string, " +
"like `expect_exact: \"some.exact.javascript;\"`");
}
test[node.label.name] = stat.body.start.value
} else {
test[node.label.name] = stat;
}
return true;
}
});

View File

@@ -1,10 +1,8 @@
var path = require("path");
var fs = require("fs");
var vm = require("vm");
var sys = require("util");
var UglifyJS = vm.createContext({
sys : sys,
console : console,
process : process,
Buffer : Buffer,
@@ -19,7 +17,7 @@ function load_global(file) {
} catch(ex) {
// XXX: in case of a syntax error, the message is kinda
// useless. (no location information).
sys.debug("ERROR in file: " + file + " / " + ex);
console.log("ERROR in file: " + file + " / " + ex);
process.exit(1);
}
};
@@ -42,7 +40,7 @@ var FILES = exports.FILES = [
FILES.forEach(load_global);
UglifyJS.AST_Node.warn_function = function(txt) {
sys.error("WARN: " + txt);
console.error("WARN: %s", txt);
};
// XXX: perhaps we shouldn't export everything but heck, I'm lazy.