[Pkg-javascript-commits] [uglifyjs] 01/04: New upstream version 2.7.4
Praveen Arimbrathodiyil
praveen at moszumanska.debian.org
Sun Nov 27 08:26:29 UTC 2016
This is an automated email from the git hooks/post-receive script.
praveen pushed a commit to branch master
in repository uglifyjs.
commit ae2e82d0b2da14e4f5a3744621a611d2f7eca946
Author: Praveen Arimbrathodiyil <praveen at debian.org>
Date: Sun Nov 27 13:23:26 2016 +0530
New upstream version 2.7.4
---
README.md | 19 +++-
bin/uglifyjs | 55 +++++-----
lib/compress.js | 39 +++++--
lib/output.js | 74 ++++++++++---
lib/scope.js | 18 +--
package.json | 2 +-
test/compress/asm.js | 4 +-
test/compress/assignment.js | 238 ++++++++++++++++++++++++++++++++++++++++
test/compress/issue-1275.js | 49 +++++++++
test/compress/reduce_vars.js | 171 +++++++++++++++++++++++++++++
test/compress/typeof.js | 22 ++++
test/compress/wrap_iife.js | 48 ++++++++
test/input/comments/filter.js | 3 +
test/input/issue-1323/sample.js | 7 ++
test/mocha/arguments.js | 8 ++
test/mocha/cli.js | 55 +++++++++-
test/mocha/comment-filter.js | 20 ++++
test/mocha/minify.js | 19 ++++
tools/node.js | 14 ++-
19 files changed, 788 insertions(+), 77 deletions(-)
diff --git a/README.md b/README.md
index 4f5b21a..789219d 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ The available options are:
--source-map-include-sources Pass this flag if you want to include the
content of source files in the source map as
sourcesContent property.
+ --source-map-inline Write base64-encoded source map to the end of js output.
--in-source-map Input source map, useful if you're compressing
JS that was generated from some other original
code.
@@ -97,8 +98,8 @@ The available options are:
"@preserve". You can optionally pass one of the
following arguments to this flag:
- "all" to keep all comments
- - a valid JS regexp (needs to start with a
- slash) to keep only comments that match.
+ - a valid JS RegExp like `/foo/` or `/^!/` to
+ keep only matching comments.
Note that currently not *all* comments can be
kept when compression is on, because of dead
code removal or cascading statements into
@@ -348,6 +349,9 @@ to set `true`; it's effectively a shortcut for `foo=true`).
- `collapse_vars` -- default `false`. Collapse single-use `var` and `const`
definitions when possible.
+- `reduce_vars` -- default `false`. Improve optimization on variables assigned
+ with and used as constant values.
+
- `warnings` -- display warnings when dropping unreachable code or unused
declarations etc.
@@ -638,7 +642,9 @@ var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {
Note that the source map is not saved in a file, it's just returned in
`result.map`. The value passed for `outSourceMap` is only used to set the
-`file` attribute in the source map (see [the spec][sm-spec]).
+`file` attribute in the source map (see [the spec][sm-spec]). You can set
+option `sourceMapInline` to be `true` and source map will be appended to
+code.
You can also specify sourceRoot property to be included in source map:
```javascript
@@ -849,8 +855,11 @@ which we care about here are `source_map` and `comments`.
#### Keeping comments in the output
In order to keep certain comments in the output you need to pass the
-`comments` option. Pass a RegExp or a function. If you pass a RegExp, only
-those comments whose body matches the regexp will be kept. Note that body
+`comments` option. Pass a RegExp (as string starting and closing with `/`
+or pass a RegExp object), a boolean or a function. Stringified options
+`all` and `some` can be passed too, where `some` behaves like it's cli
+equivalent `--comments` without passing a value. If you pass a RegExp,
+only those comments whose body matches the RegExp will be kept. Note that body
means without the initial `//` or `/*`. If you pass a function, it will be
called for every comment in the tree and will receive two arguments: the
node that the comment is attached to, and the comment token itself.
diff --git a/bin/uglifyjs b/bin/uglifyjs
index 3f0c825..ce2e941 100755
--- a/bin/uglifyjs
+++ b/bin/uglifyjs
@@ -23,6 +23,7 @@ mangling you need to use `-c` and `-m`.\
.describe("source-map", "Specify an output file where to generate source map.")
.describe("source-map-root", "The path to the original source to be included in the source map.")
.describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
+ .describe("source-map-inline", "Write base64-encoded source map to the end of js output. Disabled by default")
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
.describe("screw-ie8", "Do not support Internet Explorer 6-8 quirks. This flag is enabled by default.")
@@ -46,7 +47,7 @@ Use -c with no argument to use the default compression options.")
By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
You can optionally pass one of the following arguments to this flag:\n\
- \"all\" to keep all comments\n\
-- a valid JS regexp (needs to start with a slash) to keep only comments that match.\n\
+- a valid JS RegExp like `/foo/`or `/^!/` to keep only matching comments.\n\
\
Note that currently not *all* comments can be kept when compression is on, \
because of dead code removal or cascading statements into sequences.")
@@ -76,6 +77,7 @@ You need to pass an argument to this option to specify the name that your module
.describe("name-cache", "File to hold mangled names mappings")
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
+ .describe("wrap-iife", "Wrap IIFEs in parenthesis. Note: this disables the negate_iife compression option")
.alias("p", "prefix")
.alias("o", "output")
@@ -112,6 +114,7 @@ You need to pass an argument to this option to specify the name that your module
.array("pure-funcs")
.boolean("expr")
+ .boolean("source-map-inline")
.boolean("source-map-include-sources")
.boolean("screw-ie8")
.boolean("support-ie8")
@@ -130,6 +133,7 @@ You need to pass an argument to this option to specify the name that your module
.boolean("bare-returns")
.boolean("keep-fnames")
.boolean("reserve-domprops")
+ .boolean("wrap-iife")
.wrap(80)
@@ -247,28 +251,18 @@ if (ARGS.keep_fnames) {
if (MANGLE) MANGLE.keep_fnames = true;
}
+if (ARGS.wrap_iife) {
+ if (COMPRESS) COMPRESS.negate_iife = false;
+ OUTPUT_OPTIONS.wrap_iife = true;
+}
+
if (BEAUTIFY)
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
-if (ARGS.comments != null) {
- if (/^\/.*\/[a-zA-Z]*$/.test(ARGS.comments)) {
- try {
- OUTPUT_OPTIONS.comments = extractRegex(ARGS.comments);
- } catch (e) {
- print_error("ERROR: Invalid --comments: " + e.message);
- }
- } else if (ARGS.comments == "all") {
- OUTPUT_OPTIONS.comments = true;
- } else {
- OUTPUT_OPTIONS.comments = function(node, comment) {
- var text = comment.value;
- var type = comment.type;
- if (type == "comment2") {
- // multiline comment
- return /@preserve|@license|@cc_on/i.test(text);
- }
- }
- }
+if (ARGS.comments === "") {
+ OUTPUT_OPTIONS.comments = "some";
+} else {
+ OUTPUT_OPTIONS.comments = ARGS.comments;
}
var files = ARGS._.slice();
@@ -317,7 +311,7 @@ var TOPLEVEL = null;
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
var SOURCES_CONTENT = {};
-var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
+var SOURCE_MAP = (ARGS.source_map || ARGS.source_map_inline) ? UglifyJS.SourceMap({
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
root: ARGS.source_map_root,
orig: ORIG_MAP,
@@ -482,13 +476,18 @@ async.eachLimit(files, 1, function (file, cb) {
output = output.get();
if (SOURCE_MAP) {
- fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
- var source_map_url = ARGS.source_map_url || (
- P_RELATIVE
- ? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
- : ARGS.source_map
- );
- output += "\n//# sourceMappingURL=" + source_map_url;
+ if (ARGS.source_map_inline) {
+ var base64_string = new Buffer(SOURCE_MAP.toString()).toString('base64');
+ output += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + base64_string;
+ } else {
+ fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
+ var source_map_url = ARGS.source_map_url || (
+ P_RELATIVE
+ ? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
+ : ARGS.source_map
+ );
+ output += "\n//# sourceMappingURL=" + source_map_url;
+ }
}
if (OUTPUT_FILE) {
diff --git a/lib/compress.js b/lib/compress.js
index f8d9d32..1845717 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -67,6 +67,7 @@ function Compressor(options, false_by_default) {
if_return : !false_by_default,
join_vars : !false_by_default,
collapse_vars : false,
+ reduce_vars : false,
cascade : !false_by_default,
side_effects : !false_by_default,
pure_getters : false,
@@ -1107,7 +1108,7 @@ merge(Compressor.prototype, {
this._evaluating = true;
try {
var d = this.definition();
- if (d && d.constant && d.init) {
+ if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
return ev(d.init, compressor);
}
} finally {
@@ -2313,6 +2314,12 @@ merge(Compressor.prototype, {
// typeof always returns a non-empty string, thus it's
// always true in booleans
compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
+ if (self.expression.has_side_effects(compressor)) {
+ return make_node(AST_Seq, self, {
+ car: self.expression,
+ cdr: make_node(AST_True, self)
+ });
+ }
return make_node(AST_True, self);
}
if (e instanceof AST_Binary && self.operator == "!") {
@@ -2499,8 +2506,8 @@ merge(Compressor.prototype, {
case "+":
var ll = self.left.evaluate(compressor);
var rr = self.right.evaluate(compressor);
- if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) ||
- (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) {
+ if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1] && !self.right.has_side_effects(compressor)) ||
+ (rr.length > 1 && rr[0] instanceof AST_String && rr[1] && !self.left.has_side_effects(compressor))) {
compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
return make_node(AST_True, self);
}
@@ -2655,16 +2662,26 @@ merge(Compressor.prototype, {
});
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
+ var ASSIGN_OPS_COMMUTATIVE = [ '*', '|', '^', '&' ];
OPT(AST_Assign, function(self, compressor){
self = self.lift_sequences(compressor);
- if (self.operator == "="
- && self.left instanceof AST_SymbolRef
- && self.right instanceof AST_Binary
- && self.right.left instanceof AST_SymbolRef
- && self.right.left.name == self.left.name
- && member(self.right.operator, ASSIGN_OPS)) {
- self.operator = self.right.operator + "=";
- self.right = self.right.right;
+ if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
+ // x = expr1 OP expr2
+ if (self.right.left instanceof AST_SymbolRef
+ && self.right.left.name == self.left.name
+ && member(self.right.operator, ASSIGN_OPS)) {
+ // x = x - 2 ---> x -= 2
+ self.operator = self.right.operator + "=";
+ self.right = self.right.right;
+ }
+ else if (self.right.right instanceof AST_SymbolRef
+ && self.right.right.name == self.left.name
+ && member(self.right.operator, ASSIGN_OPS_COMMUTATIVE)
+ && !self.right.left.has_side_effects(compressor)) {
+ // x = 2 & x ---> x &= 2
+ self.operator = self.right.operator + "=";
+ self.right = self.right.left;
+ }
}
return self;
});
diff --git a/lib/output.js b/lib/output.js
index 801f751..63a78c6 100644
--- a/lib/output.js
+++ b/lib/output.js
@@ -67,9 +67,54 @@ function OutputStream(options) {
screw_ie8 : true,
preamble : null,
quote_style : 0,
- keep_quoted_props: false
+ keep_quoted_props: false,
+ wrap_iife : false,
}, true);
+ // Convert comment option to RegExp if neccessary and set up comments filter
+ if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) {
+ var regex_pos = options.comments.lastIndexOf("/");
+ options.comments = new RegExp(
+ options.comments.substr(1, regex_pos - 1),
+ options.comments.substr(regex_pos + 1)
+ );
+ }
+ if (options.comments instanceof RegExp) {
+ options.comments = (function(f) {
+ return function(comment) {
+ return comment.type == "comment5" || f.test(comment.value);
+ }
+ })(options.comments);
+ }
+ else if (typeof options.comments === "function") {
+ options.comments = (function(f) {
+ return function(comment) {
+ return comment.type == "comment5" || f(this, comment);
+ }
+ })(options.comments);
+ }
+ else if (options.comments === "some") {
+ options.comments = function(comment) {
+ var text = comment.value;
+ var type = comment.type;
+ if (type == "comment2") {
+ // multiline comment
+ return /@preserve|@license|@cc_on/i.test(text);
+ }
+ return type == "comment5";
+ }
+ }
+ else if (options.comments){ // NOTE includes "all" option
+ options.comments = function() {
+ return true;
+ }
+ } else {
+ // Falsy case, so reject all comments, except shebangs
+ options.comments = function(comment) {
+ return comment.type == "comment5";
+ }
+ }
+
var indentation = 0;
var current_col = 0;
var current_line = 1;
@@ -435,7 +480,7 @@ function OutputStream(options) {
AST_Node.DEFMETHOD("add_comments", function(output){
if (output._readonly) return;
- var c = output.option("comments"), self = this;
+ var self = this;
var start = self.start;
if (start && !start._comments_dumped) {
start._comments_dumped = true;
@@ -458,19 +503,7 @@ function OutputStream(options) {
}));
}
- if (!c) {
- comments = comments.filter(function(comment) {
- return comment.type == "comment5";
- });
- } else if (c.test) {
- comments = comments.filter(function(comment){
- return comment.type == "comment5" || c.test(comment.value);
- });
- } else if (typeof c == "function") {
- comments = comments.filter(function(comment){
- return comment.type == "comment5" || c(self, comment);
- });
- }
+ comments = comments.filter(output.option("comments"), self);
// Keep single line comments after nlb, after nlb
if (!output.option("beautify") && comments.length > 0 &&
@@ -521,7 +554,16 @@ function OutputStream(options) {
// a function expression needs parens around it when it's provably
// the first token to appear in a statement.
PARENS(AST_Function, function(output){
- return first_in_statement(output);
+ if (first_in_statement(output)) {
+ return true;
+ }
+
+ if (output.option('wrap_iife')) {
+ var p = output.parent();
+ return p instanceof AST_Call && p.expression === this;
+ }
+
+ return false;
});
// same goes for an object literal, because otherwise it would be
diff --git a/lib/scope.js b/lib/scope.js
index 606a5a2..4943b56 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -197,12 +197,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}
if (node instanceof AST_SymbolRef) {
var name = node.name;
- if (name == "eval" && tw.parent() instanceof AST_Call) {
+ var parent = tw.parent();
+ if (name == "eval" && parent instanceof AST_Call) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
}
var sym = node.scope.find_variable(name);
+ if (node.scope instanceof AST_Lambda && name == "arguments") {
+ node.scope.uses_arguments = true;
+ }
if (!sym) {
var g;
if (globals.has(name)) {
@@ -213,12 +217,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
g.global = true;
globals.set(name, g);
}
- node.thedef = g;
- if (func && name == "arguments") {
- func.uses_arguments = true;
- }
- } else {
- node.thedef = sym;
+ sym = g;
+ }
+ node.thedef = sym;
+ if (parent instanceof AST_Unary && (parent.operator === '++' || parent.operator === '--')
+ || parent instanceof AST_Assign && parent.left === node) {
+ sym.modified = true;
}
node.reference();
return true;
diff --git a/package.json b/package.json
index 4c3a807..2741f02 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon at gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
- "version": "2.7.3",
+ "version": "2.7.4",
"engines": {
"node": ">=0.8.0"
},
diff --git a/test/compress/asm.js b/test/compress/asm.js
index f392e78..9b22732 100644
--- a/test/compress/asm.js
+++ b/test/compress/asm.js
@@ -90,13 +90,13 @@ asm_mixed: {
}
function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) {
- start = 0 | start, end = 0 | end;
+ start |= 0, end |= 0;
var sum = 0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
return +sum;
}
function geometricMean(start, end) {
- return start = 0 | start, end = 0 | end, +exp(+logSum(start, end) / +(end - start | 0));
+ return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
}
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
return { geometricMean: geometricMean };
diff --git a/test/compress/assignment.js b/test/compress/assignment.js
new file mode 100644
index 0000000..903380a
--- /dev/null
+++ b/test/compress/assignment.js
@@ -0,0 +1,238 @@
+op_equals_left_local_var: {
+ options = {
+ evaluate: true,
+ }
+ input: {
+ var x;
+
+ x = x + 3;
+ x = x - 3;
+ x = x / 3;
+ x = x * 3;
+ x = x >> 3;
+ x = x << 3;
+ x = x >>> 3;
+ x = x | 3;
+ x = x ^ 3;
+ x = x % 3;
+ x = x & 3;
+
+ x = x + g();
+ x = x - g();
+ x = x / g();
+ x = x * g();
+ x = x >> g();
+ x = x << g();
+ x = x >>> g();
+ x = x | g();
+ x = x ^ g();
+ x = x % g();
+ x = x & g();
+ }
+ expect: {
+ var x;
+
+ x += 3;
+ x -= 3;
+ x /= 3;
+ x *= 3;
+ x >>= 3;
+ x <<= 3;
+ x >>>= 3;
+ x |= 3;
+ x ^= 3;
+ x %= 3;
+ x &= 3;
+
+ x += g();
+ x -= g();
+ x /= g();
+ x *= g();
+ x >>= g();
+ x <<= g();
+ x >>>= g();
+ x |= g();
+ x ^= g();
+ x %= g();
+ x &= g();
+ }
+}
+
+op_equals_right_local_var: {
+ options = {
+ evaluate: true,
+ }
+ input: {
+ var x;
+
+ x = (x -= 2) ^ x;
+
+ x = 3 + x;
+ x = 3 - x;
+ x = 3 / x;
+ x = 3 * x;
+ x = 3 >> x;
+ x = 3 << x;
+ x = 3 >>> x;
+ x = 3 | x;
+ x = 3 ^ x;
+ x = 3 % x;
+ x = 3 & x;
+
+ x = g() + x;
+ x = g() - x;
+ x = g() / x;
+ x = g() * x;
+ x = g() >> x;
+ x = g() << x;
+ x = g() >>> x;
+ x = g() | x;
+ x = g() ^ x;
+ x = g() % x;
+ x = g() & x;
+ }
+ expect: {
+ var x;
+
+ x = (x -= 2) ^ x;
+
+ x = 3 + x;
+ x = 3 - x;
+ x = 3 / x;
+ x *= 3;
+ x = 3 >> x;
+ x = 3 << x;
+ x = 3 >>> x;
+ x |= 3;
+ x ^= 3;
+ x = 3 % x;
+ x &= 3;
+
+ x = g() + x;
+ x = g() - x;
+ x = g() / x;
+ x = g() * x;
+ x = g() >> x;
+ x = g() << x;
+ x = g() >>> x;
+ x = g() | x;
+ x = g() ^ x;
+ x = g() % x;
+ x = g() & x;
+ }
+}
+op_equals_left_global_var: {
+ options = {
+ evaluate: true,
+ }
+ input: {
+ x = x + 3;
+ x = x - 3;
+ x = x / 3;
+ x = x * 3;
+ x = x >> 3;
+ x = x << 3;
+ x = x >>> 3;
+ x = x | 3;
+ x = x ^ 3;
+ x = x % 3;
+ x = x & 3;
+
+ x = x + g();
+ x = x - g();
+ x = x / g();
+ x = x * g();
+ x = x >> g();
+ x = x << g();
+ x = x >>> g();
+ x = x | g();
+ x = x ^ g();
+ x = x % g();
+ x = x & g();
+ }
+ expect: {
+ x += 3;
+ x -= 3;
+ x /= 3;
+ x *= 3;
+ x >>= 3;
+ x <<= 3;
+ x >>>= 3;
+ x |= 3;
+ x ^= 3;
+ x %= 3;
+ x &= 3;
+
+ x += g();
+ x -= g();
+ x /= g();
+ x *= g();
+ x >>= g();
+ x <<= g();
+ x >>>= g();
+ x |= g();
+ x ^= g();
+ x %= g();
+ x &= g();
+ }
+}
+
+op_equals_right_global_var: {
+ options = {
+ evaluate: true,
+ }
+ input: {
+ x = (x -= 2) ^ x;
+
+ x = 3 + x;
+ x = 3 - x;
+ x = 3 / x;
+ x = 3 * x;
+ x = 3 >> x;
+ x = 3 << x;
+ x = 3 >>> x;
+ x = 3 | x;
+ x = 3 ^ x;
+ x = 3 % x;
+ x = 3 & x;
+
+ x = g() + x;
+ x = g() - x;
+ x = g() / x;
+ x = g() * x;
+ x = g() >> x;
+ x = g() << x;
+ x = g() >>> x;
+ x = g() | x;
+ x = g() ^ x;
+ x = g() % x;
+ x = g() & x;
+ }
+ expect: {
+ x = (x -= 2) ^ x;
+
+ x = 3 + x;
+ x = 3 - x;
+ x = 3 / x;
+ x *= 3;
+ x = 3 >> x;
+ x = 3 << x;
+ x = 3 >>> x;
+ x |= 3;
+ x ^= 3;
+ x = 3 % x;
+ x &= 3;
+
+ x = g() + x;
+ x = g() - x;
+ x = g() / x;
+ x = g() * x;
+ x = g() >> x;
+ x = g() << x;
+ x = g() >>> x;
+ x = g() | x;
+ x = g() ^ x;
+ x = g() % x;
+ x = g() & x;
+ }
+}
diff --git a/test/compress/issue-1275.js b/test/compress/issue-1275.js
new file mode 100644
index 0000000..e88e284
--- /dev/null
+++ b/test/compress/issue-1275.js
@@ -0,0 +1,49 @@
+string_plus_optimization: {
+ options = {
+ side_effects : true,
+ evaluate : true,
+ conditionals : true,
+ comparisons : true,
+ dead_code : true,
+ booleans : true,
+ unused : true,
+ if_return : true,
+ join_vars : true,
+ cascade : true,
+ hoist_funs : true,
+ };
+ input: {
+ function foo(anything) {
+ function throwing_function() {
+ throw "nope";
+ }
+ try {
+ console.log('0' + throwing_function() ? "yes" : "no");
+ } catch (ex) {
+ console.log(ex);
+ }
+ console.log('0' + anything ? "yes" : "no");
+ console.log(anything + '0' ? "Yes" : "No");
+ console.log('' + anything);
+ console.log(anything + '');
+ }
+ foo();
+ }
+ expect: {
+ function foo(anything) {
+ function throwing_function() {
+ throw "nope";
+ }
+ try {
+ console.log('0' + throwing_function() ? "yes" : "no");
+ } catch (ex) {
+ console.log(ex);
+ }
+ console.log("yes");
+ console.log("Yes");
+ console.log('' + anything);
+ console.log(anything + '');
+ }
+ foo();
+ }
+}
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
new file mode 100644
index 0000000..a1d0501
--- /dev/null
+++ b/test/compress/reduce_vars.js
@@ -0,0 +1,171 @@
+reduce_vars: {
+ options = {
+ conditionals : true,
+ evaluate : true,
+ global_defs : {
+ C : 0
+ },
+ reduce_vars : true,
+ unused : true
+ }
+ input: {
+ var A = 1;
+ (function f0() {
+ var a = 2;
+ console.log(a - 5);
+ console.log(A - 5);
+ })();
+ (function f1() {
+ var a = 2;
+ console.log(a - 5);
+ eval("console.log(a);");
+ })();
+ (function f2(eval) {
+ var a = 2;
+ console.log(a - 5);
+ eval("console.log(a);");
+ })(eval);
+ (function f3() {
+ var b = typeof C !== "undefined";
+ var c = 4;
+ if (b) {
+ return 'yes';
+ } else {
+ return 'no';
+ }
+ })();
+ console.log(A + 1);
+ }
+ expect: {
+ var A = 1;
+ (function() {
+ console.log(-3);
+ console.log(-4);
+ })();
+ (function f1() {
+ var a = 2;
+ console.log(-3);
+ eval("console.log(a);");
+ })();
+ (function f2(eval) {
+ var a = 2;
+ console.log(-3);
+ eval("console.log(a);");
+ })(eval);
+ (function() {
+ return "yes";
+ })();
+ console.log(2);
+ }
+}
+
+modified: {
+ options = {
+ conditionals : true,
+ evaluate : true,
+ reduce_vars : true,
+ unused : true
+ }
+ input: {
+ function f0() {
+ var a = 1, b = 2;
+ b++;
+ console.log(a + 1);
+ console.log(b + 1);
+ }
+
+ function f1() {
+ var a = 1, b = 2;
+ --b;
+ console.log(a + 1);
+ console.log(b + 1);
+ }
+
+ function f2() {
+ var a = 1, b = 2, c = 3;
+ b = c;
+ console.log(a + b);
+ console.log(b + c);
+ console.log(a + c);
+ console.log(a + b + c);
+ }
+
+ function f3() {
+ var a = 1, b = 2, c = 3;
+ b *= c;
+ console.log(a + b);
+ console.log(b + c);
+ console.log(a + c);
+ console.log(a + b + c);
+ }
+
+ function f4() {
+ var a = 1, b = 2, c = 3;
+ if (a) {
+ b = c;
+ } else {
+ c = b;
+ }
+ console.log(a + b);
+ console.log(b + c);
+ // TODO: as "modified" is determined in "figure_out_scope",
+ // even "passes" wouldn't improve this any further
+ console.log(a + c);
+ console.log(a + b + c);
+ }
+
+ function f5(a) {
+ B = a;
+ console.log(A ? 'yes' : 'no');
+ console.log(B ? 'yes' : 'no');
+ }
+ }
+ expect: {
+ function f0() {
+ var b = 2;
+ b++;
+ console.log(2);
+ console.log(b + 1);
+ }
+
+ function f1() {
+ var b = 2;
+ --b;
+ console.log(2);
+ console.log(b + 1);
+ }
+
+ function f2() {
+ var a = 1, b = 2, c = 3;
+ b = c;
+ console.log(a + b);
+ console.log(b + c);
+ console.log(4);
+ console.log(a + b + c);
+ }
+
+ function f3() {
+ var a = 1, b = 2, c = 3;
+ b *= c;
+ console.log(a + b);
+ console.log(b + c);
+ console.log(4);
+ console.log(a + b + c);
+ }
+
+ function f4() {
+ var a = 1, b = 2, c = 3;
+ b = c;
+ console.log(a + b);
+ console.log(b + c);
+ console.log(a + c);
+ console.log(a + b + c);
+ }
+
+ function f5(a) {
+ B = a;
+ console.log(A ? 'yes' : 'no');
+ console.log(B ? 'yes' : 'no');
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/compress/typeof.js b/test/compress/typeof.js
index cefdd43..fb39157 100644
--- a/test/compress/typeof.js
+++ b/test/compress/typeof.js
@@ -23,3 +23,25 @@ typeof_evaluation: {
h='undefined';
}
}
+
+typeof_in_boolean_context: {
+ options = {
+ booleans : true,
+ evaluate : true,
+ conditionals : true,
+ };
+ input: {
+ function f1(x) { return typeof x ? "yes" : "no"; }
+ function f2() { return typeof g()? "Yes" : "No"; }
+ typeof 0 ? foo() : bar();
+ !typeof console.log(1);
+ var a = !typeof console.log(2);
+ }
+ expect: {
+ function f1(x) { return "yes"; }
+ function f2() { return g(), "Yes"; }
+ foo();
+ !(console.log(1), !0);
+ var a = !(console.log(2), !0);
+ }
+}
diff --git a/test/compress/wrap_iife.js b/test/compress/wrap_iife.js
new file mode 100644
index 0000000..5c45853
--- /dev/null
+++ b/test/compress/wrap_iife.js
@@ -0,0 +1,48 @@
+wrap_iife: {
+ options = {
+ negate_iife: false,
+ }
+ beautify = {
+ wrap_iife: true,
+ }
+ input: {
+ (function() {
+ return function() {
+ console.log('test')
+ };
+ })()();
+ }
+ expect_exact: '(function(){return function(){console.log("test")}})()();'
+}
+
+wrap_iife_in_expression: {
+ options = {
+ negate_iife: false,
+ }
+ beautify = {
+ wrap_iife: true,
+ }
+ input: {
+ foo = (function () {
+ return bar();
+ })();
+ }
+ expect_exact: 'foo=(function(){return bar()})();'
+}
+
+wrap_iife_in_return_call: {
+ options = {
+ negate_iife: false,
+ }
+ beautify = {
+ wrap_iife: true,
+ }
+ input: {
+ (function() {
+ return (function() {
+ console.log('test')
+ })();
+ })()();
+ }
+ expect_exact: '(function(){return(function(){console.log("test")})()})()();'
+}
diff --git a/test/input/comments/filter.js b/test/input/comments/filter.js
new file mode 100644
index 0000000..c752080
--- /dev/null
+++ b/test/input/comments/filter.js
@@ -0,0 +1,3 @@
+// foo
+/*@preserve*/
+// bar
diff --git a/test/input/issue-1323/sample.js b/test/input/issue-1323/sample.js
new file mode 100644
index 0000000..ff56acc
--- /dev/null
+++ b/test/input/issue-1323/sample.js
@@ -0,0 +1,7 @@
+var bar = (function () {
+ function foo (bar) {
+ return bar;
+ }
+
+ return foo;
+})();
\ No newline at end of file
diff --git a/test/mocha/arguments.js b/test/mocha/arguments.js
index 089826f..73993a7 100644
--- a/test/mocha/arguments.js
+++ b/test/mocha/arguments.js
@@ -19,4 +19,12 @@ describe("arguments", function() {
value // Select function as scope
);
});
+
+ it("Should recognize when a function uses arguments", function() {
+ var ast = UglifyJS.parse("function a(){function b(){function c(){}; return arguments[0];}}");
+ ast.figure_out_scope();
+ assert.strictEqual(ast.body[0].uses_arguments, false);
+ assert.strictEqual(ast.body[0].body[0].uses_arguments, true);
+ assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false);
+ });
});
\ No newline at end of file
diff --git a/test/mocha/cli.js b/test/mocha/cli.js
index 38b57cd..bebd4d9 100644
--- a/test/mocha/cli.js
+++ b/test/mocha/cli.js
@@ -2,11 +2,11 @@ var assert = require("assert");
var exec = require("child_process").exec;
describe("bin/uglifyjs", function () {
+ var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("should produce a functional build when using --self", function (done) {
this.timeout(5000);
- var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
- var command = uglifyjs + ' --self -cm --wrap WrappedUglifyJS';
+ var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
exec(command, function (err, stdout) {
if (err) throw err;
@@ -19,4 +19,55 @@ describe("bin/uglifyjs", function () {
done();
});
});
+ it("Should be able to filter comments correctly with `--comment all`", function (done) {
+ var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "// foo\n/*@preserve*/\n// bar\n\n");
+ done();
+ });
+ });
+ it("Should be able to filter comments correctly with `--comment <RegExp>`", function (done) {
+ var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "/*@preserve*/\n// bar\n\n");
+ done();
+ });
+ });
+ it("Should be able to filter comments correctly with just `--comment`", function (done) {
+ var command = uglifyjscmd + ' test/input/comments/filter.js --comments';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "/*@preserve*/\n\n");
+ done();
+ });
+ });
+ it("Should append source map to output when using --source-map-inline", function (done) {
+ var command = uglifyjscmd + ' test/input/issue-1323/sample.js --source-map-inline';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
+ "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=\n");
+ done();
+ });
+ });
+ it("should not append source map to output when not using --source-map-inline", function (done) {
+ var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
+ done();
+ });
+ });
});
diff --git a/test/mocha/comment-filter.js b/test/mocha/comment-filter.js
index ea2ec2e..7916275 100644
--- a/test/mocha/comment-filter.js
+++ b/test/mocha/comment-filter.js
@@ -7,6 +7,16 @@ describe("comment filters", function() {
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
+ it("Should be able to filter comments with the 'all' option", function() {
+ var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
+ assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
+ });
+
+ it("Should be able to filter commments with the 'some' option", function() {
+ var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
+ assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/\n");
+ });
+
it("Should be able to filter comments by passing a function", function() {
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
var f = function(node, comment) {
@@ -16,6 +26,11 @@ describe("comment filters", function() {
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
});
+ it("Should be able to filter comments by passing regex in string format", function() {
+ var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
+ assert.strictEqual(ast.print_to_string({comments: "/^!/"}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
+ });
+
it("Should be able to get the comment and comment type when using a function", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
var f = function(node, comment) {
@@ -42,4 +57,9 @@ describe("comment filters", function() {
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/\n");
});
+
+ it("Should never be able to filter comment5 when using 'some' as filter", function() {
+ var ast = UglifyJS.parse("#!foo\n//foo\n/*@preserve*/\n/* please hide me */");
+ assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/\n");
+ });
});
diff --git a/test/mocha/minify.js b/test/mocha/minify.js
index 2adbadc..ce5e849 100644
--- a/test/mocha/minify.js
+++ b/test/mocha/minify.js
@@ -75,4 +75,23 @@ describe("minify", function() {
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
});
});
+
+ describe("sourceMapInline", function() {
+ it("should append source map to output js when sourceMapInline is enabled", function() {
+ var result = Uglify.minify('var a = function(foo) { return foo; };', {
+ fromString: true,
+ sourceMapInline: true
+ });
+ var code = result.code;
+ assert.strictEqual(code, "var a=function(n){return n};\n" +
+ "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIj8iXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsR0FBSUEsR0FBSSxTQUFTQyxHQUFPLE1BQU9BIn0=");
+ });
+ it("should not append source map to output js when sourceMapInline is not enabled", function() {
+ var result = Uglify.minify('var a = function(foo) { return foo; };', {
+ fromString: true
+ });
+ var code = result.code;
+ assert.strictEqual(code, "var a=function(n){return n};");
+ });
+ });
});
diff --git a/tools/node.js b/tools/node.js
index 6712ccf..a16169b 100644
--- a/tools/node.js
+++ b/tools/node.js
@@ -44,6 +44,7 @@ exports.minify = function(files, options) {
sourceRoot : null,
inSourceMap : null,
sourceMapUrl : null,
+ sourceMapInline : false,
fromString : false,
warnings : false,
mangle : {},
@@ -117,7 +118,7 @@ exports.minify = function(files, options) {
if (typeof options.inSourceMap == "string") {
inMap = JSON.parse(fs.readFileSync(options.inSourceMap, "utf8"));
}
- if (options.outSourceMap) {
+ if (options.outSourceMap || options.sourceMapInline) {
output.source_map = UglifyJS.SourceMap({
file: options.outSourceMap,
orig: inMap,
@@ -138,16 +139,19 @@ exports.minify = function(files, options) {
var stream = UglifyJS.OutputStream(output);
toplevel.print(stream);
- var mappingUrlPrefix = "\n//# sourceMappingURL=";
- if (options.outSourceMap && typeof options.outSourceMap === "string" && options.sourceMapUrl !== false) {
- stream += mappingUrlPrefix + (typeof options.sourceMapUrl === "string" ? options.sourceMapUrl : options.outSourceMap);
- }
var source_map = output.source_map;
if (source_map) {
source_map = source_map + "";
}
+ var mappingUrlPrefix = "\n//# sourceMappingURL=";
+ if (options.sourceMapInline) {
+ stream += mappingUrlPrefix + "data:application/json;charset=utf-8;base64," + new Buffer(source_map).toString("base64");
+ } else if (options.outSourceMap && typeof options.outSourceMap === "string" && options.sourceMapUrl !== false) {
+ stream += mappingUrlPrefix + (typeof options.sourceMapUrl === "string" ? options.sourceMapUrl : options.outSourceMap);
+ }
+
return {
code : stream + "",
map : source_map
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git
More information about the Pkg-javascript-commits
mailing list