Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6982a0554c | ||
|
|
fa3250199a | ||
|
|
06b9894c19 | ||
|
|
9f9db504d7 | ||
|
|
82ae95c334 | ||
|
|
9a5e2052c4 | ||
|
|
b1410be443 | ||
|
|
12985d86c2 | ||
|
|
49bfc6b555 | ||
|
|
d1c6bb8c7c | ||
|
|
5c169615a8 |
@@ -1052,6 +1052,7 @@ merge(Compressor.prototype, {
|
||||
&& (side_effects || node.expression.may_throw_on_access(compressor))
|
||||
|| node instanceof AST_SymbolRef
|
||||
&& (symbol_in_lvalues(node) || side_effects && may_modify(node))
|
||||
|| node instanceof AST_This && symbol_in_lvalues(node)
|
||||
|| node instanceof AST_VarDef && node.value
|
||||
&& (node.name.name in lvalues || side_effects && may_modify(node.name))
|
||||
|| (sym = is_lhs(node.left, node))
|
||||
@@ -3525,8 +3526,9 @@ merge(Compressor.prototype, {
|
||||
var defs = [];
|
||||
vars.each(function(def, name){
|
||||
if (self instanceof AST_Lambda
|
||||
&& find_if(function(x){ return x.name == def.name.name },
|
||||
self.argnames)) {
|
||||
&& !all(self.argnames, function(argname) {
|
||||
return argname.name != name;
|
||||
})) {
|
||||
vars.del(name);
|
||||
} else {
|
||||
def = def.clone();
|
||||
@@ -3623,8 +3625,9 @@ merge(Compressor.prototype, {
|
||||
var sym = node.name, def, value;
|
||||
if (sym.scope === self
|
||||
&& (def = sym.definition()).escaped != 1
|
||||
&& !def.single_use
|
||||
&& !def.assignments
|
||||
&& !def.direct_access
|
||||
&& !def.single_use
|
||||
&& !top_retain(def)
|
||||
&& (value = sym.fixed_value()) === node.value
|
||||
&& value instanceof AST_Object) {
|
||||
@@ -4773,8 +4776,10 @@ merge(Compressor.prototype, {
|
||||
var var_def = stat.definitions[j];
|
||||
var name = var_def.name;
|
||||
append_var(decls, expressions, name, var_def.value);
|
||||
if (in_loop) {
|
||||
var def = name.definition();
|
||||
if (in_loop && all(fn.argnames, function(argname) {
|
||||
return argname.name != name.name;
|
||||
})) {
|
||||
var def = fn.variables.get(name.name);
|
||||
var sym = make_node(AST_SymbolRef, name, name);
|
||||
def.references.push(sym);
|
||||
expressions.splice(pos++, 0, make_node(AST_Assign, var_def, {
|
||||
|
||||
@@ -180,6 +180,17 @@
|
||||
end : my_end_token(M)
|
||||
};
|
||||
if (val === null) return new AST_Null(args);
|
||||
var rx = M.regex;
|
||||
if (rx && rx.pattern) {
|
||||
// RegExpLiteral as per ESTree AST spec
|
||||
args.value = new RegExp(rx.pattern, rx.flags);
|
||||
args.value.raw_source = rx.pattern;
|
||||
return new AST_RegExp(args);
|
||||
} else if (rx) {
|
||||
// support legacy RegExp
|
||||
args.value = M.regex && M.raw ? M.raw : val;
|
||||
return new AST_RegExp(args);
|
||||
}
|
||||
switch (typeof val) {
|
||||
case "string":
|
||||
args.value = val;
|
||||
@@ -189,16 +200,6 @@
|
||||
return new AST_Number(args);
|
||||
case "boolean":
|
||||
return new (val ? AST_True : AST_False)(args);
|
||||
default:
|
||||
var rx = M.regex;
|
||||
if (rx && rx.pattern) {
|
||||
// RegExpLiteral as per ESTree AST spec
|
||||
args.value = new RegExp(rx.pattern, rx.flags).toString();
|
||||
} else {
|
||||
// support legacy RegExp
|
||||
args.value = M.regex && M.raw ? M.raw : val;
|
||||
}
|
||||
return new AST_RegExp(args);
|
||||
}
|
||||
},
|
||||
Identifier: function(M) {
|
||||
@@ -410,14 +411,15 @@
|
||||
});
|
||||
|
||||
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
||||
var value = M.value;
|
||||
var flags = M.value.toString().match(/[gimuy]*$/)[0];
|
||||
var value = "/" + M.value.raw_source + "/" + flags;
|
||||
return {
|
||||
type: "Literal",
|
||||
value: value,
|
||||
raw: value.toString(),
|
||||
raw: value,
|
||||
regex: {
|
||||
pattern: value.source,
|
||||
flags: value.toString().match(/[gimuy]*$/)[0]
|
||||
pattern: M.value.raw_source,
|
||||
flags: flags
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -564,6 +566,21 @@
|
||||
FROM_MOZ_STACK = [];
|
||||
var ast = from_moz(node);
|
||||
FROM_MOZ_STACK = save_stack;
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_LabelRef) {
|
||||
for (var level = 0, parent; parent = this.parent(level); level++) {
|
||||
if (parent instanceof AST_Scope) break;
|
||||
if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
|
||||
node.thedef = parent.label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!node.thedef) {
|
||||
var s = node.start;
|
||||
js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return ast;
|
||||
};
|
||||
|
||||
|
||||
@@ -576,7 +576,7 @@ function OutputStream(options) {
|
||||
indentation : function() { return indentation },
|
||||
current_width : function() { return current_col - indentation },
|
||||
should_break : function() { return options.width && this.current_width() >= options.width },
|
||||
has_parens : function() { return OUTPUT.slice(-1) == "(" },
|
||||
has_parens : function() { return OUTPUT[OUTPUT.length - 1] == "(" },
|
||||
newline : newline,
|
||||
print : print,
|
||||
space : space,
|
||||
@@ -1484,47 +1484,52 @@ function OutputStream(options) {
|
||||
/* -----[ source map generators ]----- */
|
||||
|
||||
function DEFMAP(nodetype, generator) {
|
||||
nodetype.DEFMETHOD("add_source_map", function(stream){
|
||||
generator(this, stream);
|
||||
nodetype.forEach(function(nodetype) {
|
||||
nodetype.DEFMETHOD("add_source_map", generator);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// 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);
|
||||
};
|
||||
DEFMAP([
|
||||
// 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.
|
||||
AST_Node,
|
||||
// since the label symbol will mark it
|
||||
AST_LabeledStatement,
|
||||
AST_Toplevel,
|
||||
], noop);
|
||||
|
||||
// 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_StatementWithBody, basic_sourcemap_gen);
|
||||
DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
|
||||
DEFMAP(AST_Lambda, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Switch, basic_sourcemap_gen);
|
||||
DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
|
||||
DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Toplevel, noop);
|
||||
DEFMAP(AST_New, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Try, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Catch, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Finally, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Definitions, basic_sourcemap_gen);
|
||||
DEFMAP(AST_Constant, basic_sourcemap_gen);
|
||||
DEFMAP(AST_ObjectSetter, function(self, output){
|
||||
output.add_mapping(self.start, self.key.name);
|
||||
});
|
||||
DEFMAP(AST_ObjectGetter, function(self, output){
|
||||
output.add_mapping(self.start, self.key.name);
|
||||
});
|
||||
DEFMAP(AST_ObjectProperty, function(self, output){
|
||||
output.add_mapping(self.start, self.key);
|
||||
DEFMAP([
|
||||
AST_Array,
|
||||
AST_BlockStatement,
|
||||
AST_Catch,
|
||||
AST_Constant,
|
||||
AST_Debugger,
|
||||
AST_Definitions,
|
||||
AST_Directive,
|
||||
AST_Finally,
|
||||
AST_Jump,
|
||||
AST_Lambda,
|
||||
AST_New,
|
||||
AST_Object,
|
||||
AST_StatementWithBody,
|
||||
AST_Symbol,
|
||||
AST_Switch,
|
||||
AST_SwitchBranch,
|
||||
AST_Try,
|
||||
], function(output) {
|
||||
output.add_mapping(this.start);
|
||||
});
|
||||
|
||||
DEFMAP([
|
||||
AST_ObjectGetter,
|
||||
AST_ObjectSetter,
|
||||
], function(output) {
|
||||
output.add_mapping(this.start, this.key.name);
|
||||
});
|
||||
|
||||
DEFMAP([ AST_ObjectProperty ], function(output) {
|
||||
output.add_mapping(this.start, this.key);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -969,7 +969,9 @@ function parse($TEXT, options) {
|
||||
|
||||
function labeled_statement() {
|
||||
var label = as_symbol(AST_Label);
|
||||
if (find_if(function(l){ return l.name == label.name }, S.labels)) {
|
||||
if (!all(S.labels, function(l) {
|
||||
return l.name != label.name;
|
||||
})) {
|
||||
// ECMA-262, 12.12: An ECMAScript program is considered
|
||||
// syntactically incorrect if it contains a
|
||||
// LabelledStatement that is enclosed by a
|
||||
|
||||
36
lib/scope.js
36
lib/scope.js
@@ -100,7 +100,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
var self = this;
|
||||
var scope = self.parent_scope = null;
|
||||
var labels = new Dictionary();
|
||||
var defun = null;
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Catch) {
|
||||
@@ -115,25 +114,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
node.init_scope_vars(scope);
|
||||
var save_scope = scope;
|
||||
var save_defun = defun;
|
||||
var save_labels = labels;
|
||||
defun = scope = node;
|
||||
labels = new Dictionary();
|
||||
descend();
|
||||
scope = save_scope;
|
||||
defun = save_defun;
|
||||
labels = save_labels;
|
||||
return true; // don't descend again in TreeWalker
|
||||
}
|
||||
if (node instanceof AST_LabeledStatement) {
|
||||
var l = node.label;
|
||||
if (labels.has(l.name)) {
|
||||
throw new Error(string_template("Label {name} defined twice", l));
|
||||
}
|
||||
labels.set(l.name, l);
|
||||
descend();
|
||||
labels.del(l.name);
|
||||
return true; // no descend again
|
||||
}
|
||||
if (node instanceof AST_With) {
|
||||
for (var s = scope; s; s = s.parent_scope)
|
||||
s.uses_with = true;
|
||||
@@ -171,15 +157,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
else if (node instanceof AST_SymbolCatch) {
|
||||
scope.def_variable(node).defun = defun;
|
||||
}
|
||||
else if (node instanceof AST_LabelRef) {
|
||||
var sym = labels.get(node.name);
|
||||
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
|
||||
name: node.name,
|
||||
line: node.start.line,
|
||||
col: node.start.col
|
||||
}));
|
||||
node.thedef = sym;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
|
||||
@@ -457,16 +434,19 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
var redef = def.redefined();
|
||||
if (redef) {
|
||||
redefined.push(def);
|
||||
def.references.forEach(function(ref) {
|
||||
ref.thedef = redef;
|
||||
ref.reference(options);
|
||||
ref.thedef = def;
|
||||
});
|
||||
reference(node.argname);
|
||||
def.references.forEach(reference);
|
||||
}
|
||||
descend();
|
||||
if (!redef) mangle(def);
|
||||
return true;
|
||||
}
|
||||
|
||||
function reference(sym) {
|
||||
sym.thedef = redef;
|
||||
sym.reference(options);
|
||||
sym.thedef = def;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
redefined.forEach(mangle);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.3.16",
|
||||
"version": "3.3.17",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -5303,3 +5303,27 @@ issue_2974: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3032: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
f: function() {
|
||||
this.a = 42;
|
||||
return [ this.a, !1 ];
|
||||
}
|
||||
}.f()[0]);
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
f: function() {
|
||||
this.a = 42;
|
||||
return [ this.a, !1 ];
|
||||
}
|
||||
}.f()[0]);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
@@ -2051,3 +2051,189 @@ drop_lone_use_strict: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_3016_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 1;
|
||||
do {
|
||||
(function(a) {
|
||||
return a[b];
|
||||
var a;
|
||||
})(3);
|
||||
} while (0);
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
a = 3,
|
||||
a[b];
|
||||
} while(0);
|
||||
var a;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3016_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 1;
|
||||
do {
|
||||
(function(a) {
|
||||
return a[b];
|
||||
try {
|
||||
a = 2;
|
||||
} catch (a) {
|
||||
var a;
|
||||
}
|
||||
})(3);
|
||||
} while (0);
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
a = 3,
|
||||
a[b];
|
||||
} while(0);
|
||||
var a;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3016_2_ie8: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
ie8: true,
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 1;
|
||||
do {
|
||||
(function(a) {
|
||||
return a[b];
|
||||
try {
|
||||
a = 2;
|
||||
} catch (a) {
|
||||
var a;
|
||||
}
|
||||
})(3);
|
||||
} while (0);
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
a = 3,
|
||||
a[b];
|
||||
} while(0);
|
||||
var a;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3016_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 1;
|
||||
do {
|
||||
console.log(function() {
|
||||
return a ? "FAIL" : a = "PASS";
|
||||
try {
|
||||
a = 2;
|
||||
} catch (a) {
|
||||
var a;
|
||||
}
|
||||
}());
|
||||
} while (b--);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
|
||||
} while(b--);
|
||||
var a;
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3016_3_ie8: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
ie8: true,
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 1;
|
||||
do {
|
||||
console.log(function() {
|
||||
return a ? "FAIL" : a = "PASS";
|
||||
try {
|
||||
a = 2;
|
||||
} catch (a) {
|
||||
var a;
|
||||
}
|
||||
}());
|
||||
} while (b--);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
|
||||
} while(b--);
|
||||
var a;
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3018: {
|
||||
options = {
|
||||
inline: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 1, c = "PASS";
|
||||
do {
|
||||
(function() {
|
||||
(function(a) {
|
||||
a = 0 != (a && (c = "FAIL"));
|
||||
})();
|
||||
})();
|
||||
} while (b--);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var b = 1, c = "PASS";
|
||||
do {
|
||||
a = void 0,
|
||||
a = 0 != (a && (c = "FAIL"));
|
||||
} while (b--);
|
||||
var a;
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -686,3 +686,33 @@ undefined_key: {
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
issue_3021: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, b = 2;
|
||||
(function() {
|
||||
b = a;
|
||||
if (a++ + b--)
|
||||
return 1;
|
||||
return;
|
||||
var b = {};
|
||||
})();
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, b = 2;
|
||||
(function() {
|
||||
b = a;
|
||||
if (a++ + b--)
|
||||
return 1;
|
||||
return;
|
||||
var b = {};
|
||||
})();
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
}
|
||||
|
||||
@@ -464,3 +464,77 @@ issue_2976_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3035: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function(a) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (b) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
b && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function(o) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (t) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
t && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3035_ie8: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function(a) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (b) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
b && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function(t) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (o) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
o && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -186,99 +186,6 @@ describe("minify", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled (#1236)", function() {
|
||||
var result = Uglify.minify(read("./test/input/issue-1236/simple.js"), {
|
||||
sourceMap: {
|
||||
content: read("./test/input/issue-1236/simple.js.map"),
|
||||
filename: "simple.min.js",
|
||||
includeSources: true
|
||||
}
|
||||
});
|
||||
|
||||
var map = JSON.parse(result.map);
|
||||
|
||||
assert.equal(map.file, 'simple.min.js');
|
||||
assert.equal(map.sourcesContent.length, 1);
|
||||
assert.equal(map.sourcesContent[0],
|
||||
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
||||
});
|
||||
it("Should process inline source map", function() {
|
||||
var code = Uglify.minify(read("./test/input/issue-520/input.js"), {
|
||||
compress: { toplevel: true },
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
url: "inline"
|
||||
}
|
||||
}).code + "\n";
|
||||
assert.strictEqual(code, readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||
});
|
||||
it("Should warn for missing inline source map", function() {
|
||||
var warn_function = Uglify.AST_Node.warn_function;
|
||||
var warnings = [];
|
||||
Uglify.AST_Node.warn_function = function(txt) {
|
||||
warnings.push(txt);
|
||||
};
|
||||
try {
|
||||
var result = Uglify.minify(read("./test/input/issue-1323/sample.js"), {
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
content: "inline"
|
||||
}
|
||||
});
|
||||
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
|
||||
assert.strictEqual(warnings.length, 1);
|
||||
assert.strictEqual(warnings[0], "inline source map not found");
|
||||
} finally {
|
||||
Uglify.AST_Node.warn_function = warn_function;
|
||||
}
|
||||
});
|
||||
it("Should fail with multiple input and inline source map", function() {
|
||||
var result = Uglify.minify([
|
||||
read("./test/input/issue-520/input.js"),
|
||||
read("./test/input/issue-520/output.js")
|
||||
], {
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "Error: inline source map only works with singular input");
|
||||
});
|
||||
});
|
||||
|
||||
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; };', {
|
||||
sourceMap: {
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
var code = result.code;
|
||||
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0=");
|
||||
});
|
||||
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; };');
|
||||
var code = result.code;
|
||||
assert.strictEqual(code, "var a=function(n){return n};");
|
||||
});
|
||||
it("should work with max_line_len", function() {
|
||||
var result = Uglify.minify(read("./test/input/issue-505/input.js"), {
|
||||
output: {
|
||||
max_line_len: 20
|
||||
},
|
||||
sourceMap: {
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
assert.strictEqual(result.error, undefined);
|
||||
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("#__PURE__", function() {
|
||||
it("should drop #__PURE__ hint after use", function() {
|
||||
var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
|
||||
@@ -312,6 +219,15 @@ describe("minify", function() {
|
||||
assert.strictEqual(err.line, 1);
|
||||
assert.strictEqual(err.col, 12);
|
||||
});
|
||||
it("should reject duplicated label name", function() {
|
||||
var result = Uglify.minify("L:{L:{}}");
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Label L defined twice");
|
||||
assert.strictEqual(err.filename, "0");
|
||||
assert.strictEqual(err.line, 1);
|
||||
assert.strictEqual(err.col, 4);
|
||||
});
|
||||
});
|
||||
|
||||
describe("global_defs", function() {
|
||||
|
||||
143
test/mocha/sourcemaps.js
Normal file
143
test/mocha/sourcemaps.js
Normal file
@@ -0,0 +1,143 @@
|
||||
var assert = require("assert");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
var Uglify = require("../../");
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
function source_map(code) {
|
||||
return JSON.parse(Uglify.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: true,
|
||||
}).map);
|
||||
}
|
||||
|
||||
describe("sourcemaps", function() {
|
||||
it("Should give correct version", function() {
|
||||
var map = source_map("var x = 1 + 1;");
|
||||
assert.strictEqual(map.version, 3);
|
||||
assert.deepEqual(map.names, [ "x" ]);
|
||||
});
|
||||
|
||||
it("Should give correct names", function() {
|
||||
var map = source_map([
|
||||
"({",
|
||||
" get enabled() {",
|
||||
" return 3;",
|
||||
" },",
|
||||
" set enabled(x) {",
|
||||
" ;",
|
||||
" }",
|
||||
"});",
|
||||
].join("\n"));
|
||||
assert.deepEqual(map.names, [ "enabled", "x" ]);
|
||||
});
|
||||
|
||||
it("Should mark array/object literals", function() {
|
||||
var result = Uglify.minify([
|
||||
"var obj = {};",
|
||||
"obj.wat([]);",
|
||||
].join("\n"), {
|
||||
sourceMap: true,
|
||||
toplevel: true,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "({}).wat([]);");
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}');
|
||||
});
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled (#1236)", function() {
|
||||
var result = Uglify.minify(read("./test/input/issue-1236/simple.js"), {
|
||||
sourceMap: {
|
||||
content: read("./test/input/issue-1236/simple.js.map"),
|
||||
filename: "simple.min.js",
|
||||
includeSources: true
|
||||
}
|
||||
});
|
||||
|
||||
var map = JSON.parse(result.map);
|
||||
|
||||
assert.equal(map.file, 'simple.min.js');
|
||||
assert.equal(map.sourcesContent.length, 1);
|
||||
assert.equal(map.sourcesContent[0],
|
||||
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
||||
});
|
||||
it("Should process inline source map", function() {
|
||||
var code = Uglify.minify(read("./test/input/issue-520/input.js"), {
|
||||
compress: { toplevel: true },
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
url: "inline"
|
||||
}
|
||||
}).code + "\n";
|
||||
assert.strictEqual(code, readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||
});
|
||||
it("Should warn for missing inline source map", function() {
|
||||
var warn_function = Uglify.AST_Node.warn_function;
|
||||
var warnings = [];
|
||||
Uglify.AST_Node.warn_function = function(txt) {
|
||||
warnings.push(txt);
|
||||
};
|
||||
try {
|
||||
var result = Uglify.minify(read("./test/input/issue-1323/sample.js"), {
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
content: "inline"
|
||||
}
|
||||
});
|
||||
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
|
||||
assert.strictEqual(warnings.length, 1);
|
||||
assert.strictEqual(warnings[0], "inline source map not found");
|
||||
} finally {
|
||||
Uglify.AST_Node.warn_function = warn_function;
|
||||
}
|
||||
});
|
||||
it("Should fail with multiple input and inline source map", function() {
|
||||
var result = Uglify.minify([
|
||||
read("./test/input/issue-520/input.js"),
|
||||
read("./test/input/issue-520/output.js")
|
||||
], {
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "Error: inline source map only works with singular input");
|
||||
});
|
||||
});
|
||||
|
||||
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; };', {
|
||||
sourceMap: {
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
var code = result.code;
|
||||
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0=");
|
||||
});
|
||||
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; };');
|
||||
var code = result.code;
|
||||
assert.strictEqual(code, "var a=function(n){return n};");
|
||||
});
|
||||
it("should work with max_line_len", function() {
|
||||
var result = Uglify.minify(read("./test/input/issue-505/input.js"), {
|
||||
output: {
|
||||
max_line_len: 20
|
||||
},
|
||||
sourceMap: {
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
assert.strictEqual(result.error, undefined);
|
||||
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -23,6 +23,15 @@ describe("spidermonkey export/import sanity test", function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("should not add unnecessary escape slashes to regexps", function() {
|
||||
var input = "/[\\\\/]/;";
|
||||
var ast = uglify.parse(input).to_mozilla_ast();
|
||||
assert.equal(
|
||||
uglify.AST_Node.from_mozilla_ast(ast).print_to_string(),
|
||||
input
|
||||
);
|
||||
});
|
||||
|
||||
it("Should judge between directives and strings correctly on import", function() {
|
||||
var tests = [
|
||||
{
|
||||
|
||||
@@ -22,9 +22,6 @@ if (failures) {
|
||||
var mocha_tests = require("./mocha.js");
|
||||
mocha_tests();
|
||||
|
||||
var run_sourcemaps_tests = require('./sourcemaps');
|
||||
run_sourcemaps_tests();
|
||||
|
||||
/* -----[ utils ]----- */
|
||||
|
||||
function tmpl() {
|
||||
@@ -49,16 +46,9 @@ function log_test(name) {
|
||||
}
|
||||
|
||||
function find_test_files(dir) {
|
||||
var files = fs.readdirSync(dir).filter(function(name){
|
||||
return fs.readdirSync(dir).filter(function(name) {
|
||||
return /\.js$/i.test(name);
|
||||
});
|
||||
if (process.argv.length > 2) {
|
||||
var x = process.argv.slice(2);
|
||||
files = files.filter(function(f){
|
||||
return x.indexOf(f) >= 0;
|
||||
});
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function test_directory(dir) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
var UglifyJS = require("..");
|
||||
var ok = require("assert");
|
||||
|
||||
module.exports = function () {
|
||||
console.log("--- Sourcemaps tests");
|
||||
|
||||
var basic = source_map([
|
||||
'var x = 1 + 1;'
|
||||
].join('\n'));
|
||||
|
||||
ok.equal(basic.version, 3);
|
||||
ok.deepEqual(basic.names, ['x']);
|
||||
|
||||
var issue836 = source_map([
|
||||
"({",
|
||||
" get enabled() {",
|
||||
" return 3;",
|
||||
" },",
|
||||
" set enabled(x) {",
|
||||
" ;",
|
||||
" }",
|
||||
"});",
|
||||
].join("\n"));
|
||||
|
||||
ok.deepEqual(issue836.names, ['enabled', 'x']);
|
||||
}
|
||||
|
||||
function source_map(js) {
|
||||
return JSON.parse(UglifyJS.minify(js, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: true
|
||||
}).map);
|
||||
}
|
||||
|
||||
// Run standalone
|
||||
if (module.parent === null) {
|
||||
module.exports();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user