Compare commits
16 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f54ab16843 | ||
|
|
69cb459c16 | ||
|
|
1eae8f2dcc | ||
|
|
c4c2ef44d0 | ||
|
|
a845897758 | ||
|
|
d600c78d7b | ||
|
|
32ea2c5530 | ||
|
|
d3df2f985d | ||
|
|
69861824b5 | ||
|
|
1e0c7d2bc5 | ||
|
|
98b850580b | ||
|
|
29011ea60a | ||
|
|
77d18be073 | ||
|
|
bc61deeca9 | ||
|
|
6a5e74b44e | ||
|
|
54446341ee |
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
@@ -8,7 +8,14 @@
|
||||
|
||||
**Uglify version (`uglifyjs -V`)**
|
||||
|
||||
**JavaScript input** <!-- ideally as small as possible -->
|
||||
**JavaScript input**
|
||||
|
||||
<!--
|
||||
A complete parsable JS program exhibiting the issue with
|
||||
UglifyJS alone - without third party tools or libraries.
|
||||
Ideally the input should be as small as possible.
|
||||
Post a link to a gist if necessary.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
|
||||
@@ -697,7 +697,7 @@ var AST_Export = DEFNODE("Export", "exported_definition exported_value is_defaul
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
|
||||
name: "[AST_Destructuring|AST_SymbolConst|AST_SymbolLet|AST_SymbolVar] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
|
||||
@@ -302,6 +302,7 @@ merge(Compressor.prototype, {
|
||||
if (reduce_vars) {
|
||||
if (node instanceof AST_Toplevel) node.globals.each(reset_def);
|
||||
if (node instanceof AST_Scope) node.variables.each(reset_def);
|
||||
if (node.block_scope) node.block_scope.variables.each(reset_def);
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var d = node.definition();
|
||||
d.references.push(node);
|
||||
@@ -4823,7 +4824,8 @@ merge(Compressor.prototype, {
|
||||
arrow.is_generator = self.is_generator;
|
||||
return make_node(AST_ObjectKeyVal, self, {
|
||||
key: self.key instanceof AST_SymbolMethod ? self.key.name : self.key,
|
||||
value: arrow
|
||||
value: arrow,
|
||||
quote: self.quote,
|
||||
});
|
||||
}
|
||||
return self;
|
||||
@@ -4849,6 +4851,7 @@ merge(Compressor.prototype, {
|
||||
name: key,
|
||||
}),
|
||||
value: make_node(AST_Accessor, value, value),
|
||||
quote: self.quote,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ function minify(files, options) {
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("warnings", options, [ "compress" ]);
|
||||
var quoted_props;
|
||||
if (options.mangle) {
|
||||
options.mangle = defaults(options.mangle, {
|
||||
cache: options.nameCache && (options.nameCache.vars || {}),
|
||||
@@ -82,11 +83,16 @@ function minify(files, options) {
|
||||
safari10: false,
|
||||
toplevel: false,
|
||||
}, true);
|
||||
if (options.nameCache && options.mangle.properties) {
|
||||
if (options.mangle.properties) {
|
||||
if (typeof options.mangle.properties != "object") {
|
||||
options.mangle.properties = {};
|
||||
}
|
||||
if (!("cache" in options.mangle.properties)) {
|
||||
if (options.mangle.properties.keep_quoted) {
|
||||
quoted_props = options.mangle.properties.reserved;
|
||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||
options.mangle.properties.reserved = quoted_props;
|
||||
}
|
||||
if (options.nameCache && !("cache" in options.mangle.properties)) {
|
||||
options.mangle.properties.cache = options.nameCache.props || {};
|
||||
}
|
||||
}
|
||||
@@ -129,6 +135,9 @@ function minify(files, options) {
|
||||
}
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (quoted_props) {
|
||||
reserve_quoted_keys(toplevel, quoted_props);
|
||||
}
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ function OutputStream(options) {
|
||||
|
||||
options = defaults(options, {
|
||||
ascii_only : false,
|
||||
ascii_identifiers: undefined,
|
||||
beautify : false,
|
||||
bracketize : false,
|
||||
comments : false,
|
||||
@@ -78,9 +77,6 @@ function OutputStream(options) {
|
||||
wrap_iife : false,
|
||||
}, true);
|
||||
|
||||
if (typeof options.ascii_identifiers === 'undefined')
|
||||
options.ascii_identifiers = options.ascii_only;
|
||||
|
||||
if (options.shorthand === undefined)
|
||||
options.shorthand = options.ecma > 5;
|
||||
|
||||
@@ -118,20 +114,16 @@ function OutputStream(options) {
|
||||
var current_pos = 0;
|
||||
var OUTPUT = "";
|
||||
|
||||
function to_ascii(str, identifier) {
|
||||
return str.replace(/[\ud800-\udbff][\udc00-\udfff]|[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||
var code = get_full_char_code(ch, 0).toString(16);
|
||||
|
||||
if ((identifier && code.length === 1 && options.ecma >= 6) || code.length > 4) {
|
||||
if (options.ecma < 6) {
|
||||
if (identifier) {
|
||||
return ch; // no \u{} support
|
||||
}
|
||||
return "\\u" + ch.charCodeAt(0).toString(16) + "\\u"
|
||||
+ ch.charCodeAt(1).toString(16);
|
||||
}
|
||||
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
||||
if (options.ecma >= 6) {
|
||||
str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
|
||||
var code = get_full_char_code(ch, 0).toString(16);
|
||||
return "\\u{" + code + "}";
|
||||
} else if (code.length <= 2 && !identifier) {
|
||||
});
|
||||
}
|
||||
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||
var code = ch.charCodeAt(0).toString(16);
|
||||
if (code.length <= 2 && !identifier) {
|
||||
while (code.length < 2) code = "0" + code;
|
||||
return "\\x" + code;
|
||||
} else {
|
||||
@@ -139,6 +131,12 @@ function OutputStream(options) {
|
||||
return "\\u" + code;
|
||||
}
|
||||
});
|
||||
} : function(str) {
|
||||
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
|
||||
return "\\u" + ch.charCodeAt(0).toString(16);
|
||||
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
|
||||
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
|
||||
});
|
||||
};
|
||||
|
||||
function make_string(str, quote) {
|
||||
@@ -172,7 +170,7 @@ function OutputStream(options) {
|
||||
function quote_template() {
|
||||
return '`' + str.replace(/`/g, '\\`') + '`';
|
||||
}
|
||||
if (options.ascii_only) str = to_ascii(str);
|
||||
str = to_utf8(str);
|
||||
if (quote === "`") return quote_template();
|
||||
switch (options.quote_style) {
|
||||
case 1:
|
||||
@@ -198,8 +196,7 @@ function OutputStream(options) {
|
||||
|
||||
function make_name(name) {
|
||||
name = name.toString();
|
||||
if (options.ascii_identifiers)
|
||||
name = to_ascii(name, true);
|
||||
name = to_utf8(name, true);
|
||||
return name;
|
||||
};
|
||||
|
||||
@@ -461,7 +458,7 @@ function OutputStream(options) {
|
||||
last : function() { return last },
|
||||
semicolon : semicolon,
|
||||
force_semicolon : force_semicolon,
|
||||
to_ascii : to_ascii,
|
||||
to_utf8 : to_utf8,
|
||||
print_name : function(name) { print(make_name(name)) },
|
||||
print_string : function(str, quote, escape_directive) {
|
||||
var encoded = encode_string(str, quote);
|
||||
@@ -1713,9 +1710,7 @@ function OutputStream(options) {
|
||||
if (regexp.raw_source) {
|
||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||
}
|
||||
if (output.option("ascii_only")) {
|
||||
str = output.to_ascii(str);
|
||||
}
|
||||
str = output.to_utf8(str);
|
||||
output.print(str);
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||
|
||||
@@ -85,6 +85,36 @@ function find_builtins(reserved) {
|
||||
}
|
||||
}
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty && node.quote) {
|
||||
add(node.key.name);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function addStrings(node, add) {
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
addStrings(node.expressions[node.expressions.length - 1], add);
|
||||
} else if (node instanceof AST_String) {
|
||||
add(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
addStrings(node.consequent, add);
|
||||
addStrings(node.alternative, add);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options) {
|
||||
options = defaults(options, {
|
||||
builtins: false,
|
||||
@@ -109,7 +139,6 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
var regex = options.regex;
|
||||
var keep_quoted = options.keep_quoted;
|
||||
|
||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||
@@ -122,12 +151,11 @@ function mangle_properties(ast, options) {
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var to_keep = {};
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
add(node.key, keep_quoted && node.quote);
|
||||
add(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
@@ -137,18 +165,14 @@ function mangle_properties(ast, options) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, keep_quoted);
|
||||
}
|
||||
else if (node instanceof AST_ConciseMethod) {
|
||||
add(node.name.name);
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (!(keep_quoted && node.quote))
|
||||
node.key = mangle(node.key);
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter
|
||||
@@ -157,27 +181,9 @@ function mangle_properties(ast, options) {
|
||||
else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
if (!keep_quoted)
|
||||
node.property = mangleStrings(node.property);
|
||||
else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||
node.property = mangleStrings(node.property);
|
||||
}
|
||||
else if (node instanceof AST_ConciseMethod) {
|
||||
if (should_mangle(node.name.name)) {
|
||||
node.name.name = mangle(node.name.name);
|
||||
}
|
||||
}
|
||||
// else if (node instanceof AST_String) {
|
||||
// if (should_mangle(node.value)) {
|
||||
// AST_Node.warn(
|
||||
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
|
||||
// file : node.start.file,
|
||||
// line : node.start.line,
|
||||
// col : node.start.col,
|
||||
// prop : node.value
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}));
|
||||
|
||||
// only function declarations after this line
|
||||
@@ -193,19 +199,13 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (keep_quoted && name in to_keep) return false;
|
||||
if (regex && !regex.test(name)) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
return cache.props.has(name)
|
||||
|| names_to_mangle.indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
function add(name, keep) {
|
||||
if (keep) {
|
||||
to_keep[name] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
if (can_mangle(name))
|
||||
push_uniq(names_to_mangle, name);
|
||||
|
||||
@@ -225,19 +225,16 @@ function mangle_properties(ast, options) {
|
||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||
|
||||
if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
|
||||
if (can_mangle(debug_mangled)) {
|
||||
mangled = debug_mangled;
|
||||
}
|
||||
}
|
||||
|
||||
// either debug mode is off, or it is on and we could not use the mangled name
|
||||
if (!mangled) {
|
||||
// Note: `can_mangle()` does not check if the name collides with the `to_keep` set
|
||||
// (filled with quoted properties when `keep_quoted` is set). Make sure we add this
|
||||
// check so we don't collide with a quoted name.
|
||||
do {
|
||||
mangled = base54(++cache.cname);
|
||||
} while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
|
||||
} while (!can_mangle(mangled));
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
@@ -245,32 +242,6 @@ function mangle_properties(ast, options) {
|
||||
return mangled;
|
||||
}
|
||||
|
||||
function addStrings(node, keep) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Sequence) {
|
||||
walk(node.expressions[node.expressions.length - 1]);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_String) {
|
||||
add(node.value, keep);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Conditional) {
|
||||
walk(node.consequent);
|
||||
walk(node.alternative);
|
||||
return true;
|
||||
}
|
||||
throw out;
|
||||
}));
|
||||
})(node);
|
||||
} catch(ex) {
|
||||
if (ex !== out) throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
function mangleStrings(node) {
|
||||
return node.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_Sequence) {
|
||||
|
||||
@@ -116,7 +116,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node.is_block_scope()) {
|
||||
var save_scope = scope;
|
||||
scope = new AST_Scope(node);
|
||||
node.block_scope = scope = new AST_Scope(node);
|
||||
scope.init_scope_vars(save_scope);
|
||||
if (!(node instanceof AST_Scope)) {
|
||||
scope.uses_with = save_scope.uses_with;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.0.25",
|
||||
"version": "3.0.27",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -26,12 +26,12 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.9.0",
|
||||
"commander": "~2.11.0",
|
||||
"source-map": "~0.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~5.0.3",
|
||||
"mocha": "~2.3.4",
|
||||
"acorn": "~5.1.1",
|
||||
"mocha": "~3.4.2",
|
||||
"semver": "~5.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -2548,3 +2548,71 @@ duplicate_argname: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2250_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
if (x) {
|
||||
const a = foo();
|
||||
x(a);
|
||||
}
|
||||
}
|
||||
function g(x) {
|
||||
if (x) {
|
||||
let a = foo();
|
||||
x(a);
|
||||
}
|
||||
}
|
||||
function h(x) {
|
||||
if (x) {
|
||||
var a = foo();
|
||||
x(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x) {
|
||||
x && x(foo());
|
||||
}
|
||||
function g(x) {
|
||||
x && x(foo());
|
||||
}
|
||||
function h(x) {
|
||||
x && x(foo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2250_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
{
|
||||
const foo = function(){};
|
||||
foo(bar());
|
||||
}
|
||||
{
|
||||
let foo = function(){};
|
||||
foo(bar());
|
||||
}
|
||||
{
|
||||
var foo = function(){};
|
||||
foo(bar());
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
issue_1321_no_debug: {
|
||||
mangle_props = {
|
||||
keep_quoted: true
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -10,17 +12,19 @@ issue_1321_no_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["a"] = 2 * x.o;
|
||||
console.log(x.o, x["a"]);
|
||||
x.x = 1;
|
||||
x["a"] = 2 * x.x;
|
||||
console.log(x.x, x["a"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
keep_quoted: true,
|
||||
debug: ""
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -30,16 +34,18 @@ issue_1321_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["_$foo$_"] = 2 * x.o;
|
||||
console.log(x.o, x["_$foo$_"]);
|
||||
x.x = 1;
|
||||
x["_$foo$_"] = 2 * x.x;
|
||||
console.log(x.x, x["_$foo$_"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_with_quoted: {
|
||||
mangle_props = {
|
||||
keep_quoted: false
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -49,9 +55,9 @@ issue_1321_with_quoted: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["x"] = 2 * x.o;
|
||||
console.log(x.o, x["x"]);
|
||||
x.x = 1;
|
||||
x["o"] = 2 * x.x;
|
||||
console.log(x.x, x["o"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mangle_props: {
|
||||
mangle_props = {}
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
@@ -54,10 +56,12 @@ mangle_props: {
|
||||
}
|
||||
|
||||
numeric_literal: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
0: 0,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
dont_reuse_prop: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
@@ -20,8 +22,10 @@ dont_reuse_prop: {
|
||||
}
|
||||
|
||||
unmangleable_props_should_always_be_reserved: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
|
||||
@@ -284,9 +284,11 @@ concise_methods_with_various_property_names: {
|
||||
}
|
||||
|
||||
concise_methods_and_mangle_props: {
|
||||
mangle_props = {
|
||||
regex: /_/
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /_/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
obj = {
|
||||
|
||||
@@ -128,9 +128,11 @@ evaluate_string_length: {
|
||||
}
|
||||
|
||||
mangle_properties: {
|
||||
mangle_props = {
|
||||
keep_quoted: false
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
@@ -139,11 +141,11 @@ mangle_properties: {
|
||||
a['run']({color: "blue", foo: "baz"});
|
||||
}
|
||||
expect: {
|
||||
a["o"] = "bar";
|
||||
a.a = "red";
|
||||
x = {r: 10};
|
||||
a.b(x.r, a.o);
|
||||
a['b']({a: "blue", o: "baz"});
|
||||
a["a"] = "bar";
|
||||
a.b = "red";
|
||||
x = {o: 10};
|
||||
a.r(x.o, a.a);
|
||||
a['r']({b: "blue", a: "baz"});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +153,11 @@ mangle_unquoted_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
builtins: true,
|
||||
keep_quoted: true
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -182,24 +186,26 @@ mangle_unquoted_properties: {
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.o = 2;
|
||||
x = {"bar": 10, f: 7};
|
||||
a.f = 9;
|
||||
a.r = 2;
|
||||
x = {"bar": 10, b: 7};
|
||||
a.b = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, f: 7};
|
||||
a.f = 9;
|
||||
a.o = 3;
|
||||
x = {bar: 10, b: 7};
|
||||
a.b = 9;
|
||||
a.r = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug: {
|
||||
mangle_props = {
|
||||
debug: ""
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -211,9 +217,11 @@ mangle_debug: {
|
||||
}
|
||||
|
||||
mangle_debug_true: {
|
||||
mangle_props = {
|
||||
debug: true
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -225,9 +233,11 @@ mangle_debug_true: {
|
||||
}
|
||||
|
||||
mangle_debug_suffix: {
|
||||
mangle_props = {
|
||||
debug: "XYZ"
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "XYZ",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -242,11 +252,13 @@ mangle_debug_suffix_keep_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
builtins: true,
|
||||
keep_quoted: true,
|
||||
debug: "XYZ",
|
||||
reserved: []
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
debug: "XYZ",
|
||||
keep_quoted: true,
|
||||
reserved: [],
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -870,3 +882,85 @@ issue_2208_9: {
|
||||
expect_stdout: "42"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
methods_keep_quoted_true: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { "Quoted"(){} Unquoted(){} }
|
||||
f1({ "Quoted"(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ "Quoted": function(){} });
|
||||
f3({ "Quoted": ()=>{} });
|
||||
}
|
||||
expect_exact: "class C{Quoted(){}o(){}}f1({Quoted(){},o(){},Prop:3});f2({Quoted(){}});f3({Quoted(){}});"
|
||||
}
|
||||
|
||||
methods_keep_quoted_false: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { "Quoted"(){} Unquoted(){} }
|
||||
f1({ "Quoted"(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ "Quoted": function(){} });
|
||||
f3({ "Quoted": ()=>{} });
|
||||
}
|
||||
expect_exact: "class C{o(){}d(){}}f1({o(){},d(){},e:3});f2({o(){}});f3({o(){}});"
|
||||
}
|
||||
|
||||
methods_keep_quoted_from_dead_code: {
|
||||
options = {
|
||||
arrows: true,
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { Quoted(){} Unquoted(){} }
|
||||
f1({ Quoted(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ Quoted: function(){} });
|
||||
f3({ Quoted: ()=>{} });
|
||||
0 && obj["Quoted"];
|
||||
}
|
||||
expect_exact: "class C{Quoted(){}o(){}}f1({Quoted(){},o(){},Prop:3});f2({Quoted(){}});f3({Quoted(){}});"
|
||||
}
|
||||
|
||||
issue_2256: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
({ "keep": 1 });
|
||||
g.keep = g.change;
|
||||
}
|
||||
expect: {
|
||||
g.keep = g.g;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,15 +43,6 @@ unicode_string_literals: {
|
||||
expect_exact: 'var a="6 length unicode character: \\u{101111}";'
|
||||
}
|
||||
|
||||
// Don't escape identifiers below es6 (or in this case double escaped in expect_exact)
|
||||
unicode_output_es5_surrogates: {
|
||||
beautify = {ascii_only: true, ecma: 5}
|
||||
input: {
|
||||
var \u{10000} = "6 length unicode character: \u{10FFFF}";
|
||||
}
|
||||
expect_exact: 'var \u{10000}="6 length unicode character: \\udbff\\udfff";'
|
||||
}
|
||||
|
||||
check_escape_style: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
@@ -65,20 +56,6 @@ check_escape_style: {
|
||||
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \\u{10000}="\\u{10000}";var \\u{2f800}="\\u{100000}";'
|
||||
}
|
||||
|
||||
// Don't escape identifiers below es6, no escaped identifiers support and no \u{} syntax
|
||||
check_escape_style_es5: {
|
||||
beautify = {ascii_only: true, ecma: 5}
|
||||
input: {
|
||||
var a = "\x01";
|
||||
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
|
||||
var \u0100 = "\u0100";
|
||||
var \u1000 = "\u1000";
|
||||
var \u{10000} = "\u{10000}"; // Identifier won't be escaped in es 5.1
|
||||
var \u{2f800} = "\u{100000}"; // Same
|
||||
}
|
||||
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \ud800\udc00="\\ud800\\udc00";var \ud87e\udc00="\\udbc0\\udc00";'
|
||||
}
|
||||
|
||||
ID_continue_with_surrogate_pair: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
@@ -103,18 +80,42 @@ non_escape_2_non_escape: {
|
||||
expect_exact: 'var µþ="µþ";'
|
||||
}
|
||||
|
||||
non_escape_2_half_escape1: {
|
||||
beautify = {ascii_only: false, ascii_identifiers: true, ecma: 6}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
issue_2242_1: {
|
||||
beautify = {
|
||||
ascii_only: false,
|
||||
}
|
||||
expect_exact: 'var \\u00b5\\u00fe="µþ";'
|
||||
input: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
non_escape_2_half_escape2: {
|
||||
beautify = {ascii_only: true, ascii_identifiers: false, ecma: 6}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
issue_2242_2: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
expect_exact: 'var µþ="\\xb5\\xfe";'
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_3: {
|
||||
options = {
|
||||
evaluate: false,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ exports["defaults"] = defaults;
|
||||
exports["mangle_properties"] = mangle_properties;
|
||||
exports["minify"] = minify;
|
||||
exports["parse"] = parse;
|
||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||
exports["string_template"] = string_template;
|
||||
exports["tokenizer"] = tokenizer;
|
||||
exports["is_identifier"] = is_identifier;
|
||||
|
||||
@@ -124,6 +124,17 @@ describe("minify", function() {
|
||||
assert.strictEqual(result.code,
|
||||
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||
});
|
||||
it("Should not mangle quoted property within dead code", function() {
|
||||
var result = Uglify.minify('({ "keep": 1 }); g.keep = g.change;', {
|
||||
mangle: {
|
||||
properties: {
|
||||
keep_quoted: true
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "g.keep=g.g;");
|
||||
});
|
||||
});
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
|
||||
@@ -78,4 +78,41 @@ describe("String literals", function() {
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\08";');
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\09";');
|
||||
});
|
||||
|
||||
it("Should not unescape unpaired surrogates", function() {
|
||||
var code = [];
|
||||
for (var i = 0; i <= 0xF; i++) {
|
||||
code.push("\\u000" + i.toString(16));
|
||||
}
|
||||
for (;i <= 0xFF; i++) {
|
||||
code.push("\\u00" + i.toString(16));
|
||||
}
|
||||
for (;i <= 0xFFF; i++) {
|
||||
code.push("\\u0" + i.toString(16));
|
||||
}
|
||||
for (; i <= 0xFFFF; i++) {
|
||||
code.push("\\u" + i.toString(16));
|
||||
}
|
||||
code = '"' + code.join() + '"';
|
||||
var normal = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ascii_only: false
|
||||
}
|
||||
});
|
||||
if (normal.error) throw normal.error;
|
||||
assert.ok(code.length > normal.code.length);
|
||||
assert.strictEqual(eval(code), eval(normal.code));
|
||||
var ascii = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ascii_only: false
|
||||
}
|
||||
});
|
||||
if (ascii.error) throw ascii.error;
|
||||
assert.ok(code.length > ascii.code.length);
|
||||
assert.strictEqual(eval(code), eval(ascii.code));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var semver = require("semver");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Unicode", function() {
|
||||
@@ -138,8 +139,33 @@ describe("Unicode", function() {
|
||||
|
||||
it("Should parse raw characters correctly", function() {
|
||||
var ast = uglify.parse('console.log("\\udbff");');
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\udbff");');
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\\udbff");');
|
||||
ast = uglify.parse(ast.print_to_string());
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\udbff");');
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\\udbff");');
|
||||
});
|
||||
|
||||
if (semver.satisfies(process.version, ">=4")) {
|
||||
it("Should not unescape unpaired surrogates", function() {
|
||||
var code = [];
|
||||
for (var i = 0; i <= 0x20001; i++) {
|
||||
code.push("\\u{" + i.toString(16) + "}");
|
||||
}
|
||||
code = '"' + code.join() + '"';
|
||||
[true, false].forEach(function(ascii_only) {
|
||||
[5, 6].forEach(function(ecma) {
|
||||
var result = uglify.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ascii_only: ascii_only
|
||||
},
|
||||
ecma: ecma
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
if (ecma > 5) assert.ok(code.length > result.code.length);
|
||||
assert.strictEqual(eval(code), eval(result.code));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -111,18 +111,22 @@ function run_compress_tests() {
|
||||
};
|
||||
if (!options.warnings) options.warnings = true;
|
||||
}
|
||||
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
||||
var quoted_props = test.mangle.properties.reserved;
|
||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||
test.mangle.properties.reserved = quoted_props;
|
||||
U.reserve_quoted_keys(input, quoted_props);
|
||||
}
|
||||
var cmp = new U.Compressor(options, true);
|
||||
var output = cmp.compress(input);
|
||||
output.figure_out_scope(test.mangle);
|
||||
if (test.mangle || test.mangle_props) {
|
||||
if (test.mangle) {
|
||||
U.base54.reset();
|
||||
output.compute_char_frequency(test.mangle);
|
||||
}
|
||||
if (test.mangle) {
|
||||
output.mangle_names(test.mangle);
|
||||
}
|
||||
if (test.mangle_props) {
|
||||
output = U.mangle_properties(output, test.mangle_props);
|
||||
if (test.mangle.properties) {
|
||||
output = U.mangle_properties(output, test.mangle.properties);
|
||||
}
|
||||
}
|
||||
output = make_code(output, output_options);
|
||||
if (expect != output) {
|
||||
|
||||
Reference in New Issue
Block a user