improve usability of --mangle-props (#5669)
This commit is contained in:
12
README.md
12
README.md
@@ -327,7 +327,7 @@ unquoted style (`o.foo`). Example:
|
|||||||
// stuff.js
|
// stuff.js
|
||||||
var o = {
|
var o = {
|
||||||
"foo": 1,
|
"foo": 1,
|
||||||
bar: 3
|
bar: 3,
|
||||||
};
|
};
|
||||||
o.foo += o.bar;
|
o.foo += o.bar;
|
||||||
console.log(o.foo);
|
console.log(o.foo);
|
||||||
@@ -339,6 +339,16 @@ $ uglifyjs stuff.js --mangle-props keep_quoted -c -m
|
|||||||
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
|
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the minified output will be processed again by UglifyJS, consider specifying
|
||||||
|
`keep_quoted_props` so the same property names are preserved:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m -O keep_quoted_props
|
||||||
|
```
|
||||||
|
```javascript
|
||||||
|
var o={"foo":1,o:3};o.foo+=o.o,console.log(o.foo);
|
||||||
|
```
|
||||||
|
|
||||||
### Debugging property name mangling
|
### Debugging property name mangling
|
||||||
|
|
||||||
You can also pass `--mangle-props debug` in order to mangle property names
|
You can also pass `--mangle-props debug` in order to mangle property names
|
||||||
|
|||||||
@@ -1519,7 +1519,7 @@ var AST_New = DEFNODE("New", null, {
|
|||||||
var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
||||||
$documentation: "A sequence expression (comma-separated expressions)",
|
$documentation: "A sequence expression (comma-separated expressions)",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
expressions: "[AST_Node*] array of expressions (at least two)"
|
expressions: "[AST_Node*] array of expressions (at least two)",
|
||||||
},
|
},
|
||||||
_equals: function(node) {
|
_equals: function(node) {
|
||||||
return all_equals(this.expressions, node.expressions);
|
return all_equals(this.expressions, node.expressions);
|
||||||
@@ -1568,8 +1568,11 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression optional property termina
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
var AST_Dot = DEFNODE("Dot", null, {
|
var AST_Dot = DEFNODE("Dot", "quoted", {
|
||||||
$documentation: "A dotted property access expression",
|
$documentation: "A dotted property access expression",
|
||||||
|
$propdoc: {
|
||||||
|
quoted: "[boolean] whether property is transformed from a quoted string",
|
||||||
|
},
|
||||||
walk: function(visitor) {
|
walk: function(visitor) {
|
||||||
var node = this;
|
var node = this;
|
||||||
visitor.visit(node, function() {
|
visitor.visit(node, function() {
|
||||||
@@ -1618,7 +1621,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
|
|||||||
$documentation: "Base class for unary expressions",
|
$documentation: "Base class for unary expressions",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
operator: "[string] the operator",
|
operator: "[string] the operator",
|
||||||
expression: "[AST_Node] expression that this unary operator applies to"
|
expression: "[AST_Node] expression that this unary operator applies to",
|
||||||
},
|
},
|
||||||
_equals: function(node) {
|
_equals: function(node) {
|
||||||
return this.operator == node.operator
|
return this.operator == node.operator
|
||||||
|
|||||||
@@ -13236,6 +13236,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
optional: self.optional,
|
optional: self.optional,
|
||||||
expression: expr,
|
expression: expr,
|
||||||
property: property,
|
property: property,
|
||||||
|
quoted: true,
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ function minify(files, options) {
|
|||||||
toplevel.mangle_names(options.mangle);
|
toplevel.mangle_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.properties = Date.now();
|
if (timings) timings.properties = Date.now();
|
||||||
|
if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);
|
||||||
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
|
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
|
||||||
if (options.parse.expression) toplevel = toplevel.unwrap_expression();
|
if (options.parse.expression) toplevel = toplevel.unwrap_expression();
|
||||||
if (timings) timings.output = Date.now();
|
if (timings) timings.output = Date.now();
|
||||||
|
|||||||
@@ -1517,7 +1517,7 @@ function OutputStream(options) {
|
|||||||
var expr = self.expression;
|
var expr = self.expression;
|
||||||
expr.print(output);
|
expr.print(output);
|
||||||
var prop = self.property;
|
var prop = self.property;
|
||||||
if (output.option("ie") && RESERVED_WORDS[prop]) {
|
if (output.option("ie") && RESERVED_WORDS[prop] || self.quoted && output.option("keep_quoted_props")) {
|
||||||
if (self.optional) output.print("?.");
|
if (self.optional) output.print("?.");
|
||||||
output.with_square(function() {
|
output.with_square(function() {
|
||||||
output.add_mapping(self.end);
|
output.add_mapping(self.end);
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ function reserve_quoted_keys(ast, reserved) {
|
|||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ClassProperty) {
|
if (node instanceof AST_ClassProperty) {
|
||||||
if (node.start && node.start.quote) add(node.key);
|
if (node.start && node.start.quote) add(node.key);
|
||||||
|
} else if (node instanceof AST_Dot) {
|
||||||
|
if (node.quoted) add(node.property);
|
||||||
} else if (node instanceof AST_ObjectProperty) {
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
if (node.start && node.start.quote) add(node.key);
|
if (node.start && node.start.quote) add(node.key);
|
||||||
} else if (node instanceof AST_Sub) {
|
} else if (node instanceof AST_Sub) {
|
||||||
|
|||||||
@@ -307,8 +307,9 @@ function test_case(test) {
|
|||||||
warnings_emitted.push(text);
|
warnings_emitted.push(text);
|
||||||
}, /"INFO: /.test(expected_warnings));
|
}, /"INFO: /.test(expected_warnings));
|
||||||
}
|
}
|
||||||
|
var quoted_props;
|
||||||
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
||||||
var quoted_props = test.mangle.properties.reserved;
|
quoted_props = test.mangle.properties.reserved;
|
||||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||||
test.mangle.properties.reserved = quoted_props;
|
test.mangle.properties.reserved = quoted_props;
|
||||||
U.reserve_quoted_keys(input, quoted_props);
|
U.reserve_quoted_keys(input, quoted_props);
|
||||||
@@ -323,6 +324,7 @@ function test_case(test) {
|
|||||||
if (test.mangle) {
|
if (test.mangle) {
|
||||||
output.compute_char_frequency(test.mangle);
|
output.compute_char_frequency(test.mangle);
|
||||||
output.mangle_names(test.mangle);
|
output.mangle_names(test.mangle);
|
||||||
|
if (quoted_props) U.reserve_quoted_keys(input, quoted_props);
|
||||||
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
|
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
|
||||||
}
|
}
|
||||||
var output_code = make_code(output, output_options, test.expression);
|
var output_code = make_code(output, output_options, test.expression);
|
||||||
|
|||||||
@@ -353,6 +353,68 @@ mangle_debug_suffix_keep_quoted: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keep_substituted_property: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
properties: {
|
||||||
|
keep_quoted: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { p: [] };
|
||||||
|
function f(b) {
|
||||||
|
return o[b];
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
var a = "p";
|
||||||
|
return o[a] === f(a);
|
||||||
|
}
|
||||||
|
console.log(g() ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = { p: [] };
|
||||||
|
function f(n) {
|
||||||
|
return o[n];
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
var n = "p";
|
||||||
|
return o.p === f(n);
|
||||||
|
}
|
||||||
|
console.log(g() ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_substituted_property_quotes: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
keep_quoted_props: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(o) {
|
||||||
|
var a = "p";
|
||||||
|
return o[a];
|
||||||
|
}
|
||||||
|
console.log(f({ p: "PASS" }));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(o) {
|
||||||
|
var a = "p";
|
||||||
|
return o["p"];
|
||||||
|
}
|
||||||
|
console.log(f({ p: "PASS" }));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
first_256_chars_as_properties: {
|
first_256_chars_as_properties: {
|
||||||
beautify = {
|
beautify = {
|
||||||
ascii_only: true,
|
ascii_only: true,
|
||||||
@@ -899,12 +961,15 @@ issue_2256: {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({ "keep": 1 });
|
({ "keep": 42 });
|
||||||
g.keep = g.change;
|
global.keep = global.change;
|
||||||
|
console.log(keep);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
g.keep = g.g;
|
global.keep = global.l;
|
||||||
|
console.log(keep);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs_prop_1: {
|
lhs_prop_1: {
|
||||||
|
|||||||
Reference in New Issue
Block a user