Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve usability of --mangle-props #5669

Merged
merged 1 commit into from
Sep 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ unquoted style (`o.foo`). Example:
// stuff.js
var o = {
"foo": 1,
bar: 3
bar: 3,
};
o.foo += o.bar;
console.log(o.foo);
Expand All @@ -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);
```

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

You can also pass `--mangle-props debug` in order to mangle property names
Expand Down
9 changes: 6 additions & 3 deletions lib/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,7 @@ var AST_New = DEFNODE("New", null, {
var AST_Sequence = DEFNODE("Sequence", "expressions", {
$documentation: "A sequence expression (comma-separated expressions)",
$propdoc: {
expressions: "[AST_Node*] array of expressions (at least two)"
expressions: "[AST_Node*] array of expressions (at least two)",
},
_equals: function(node) {
return all_equals(this.expressions, node.expressions);
Expand Down Expand Up @@ -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",
$propdoc: {
quoted: "[boolean] whether property is transformed from a quoted string",
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
Expand Down Expand Up @@ -1618,7 +1621,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
$documentation: "Base class for unary expressions",
$propdoc: {
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) {
return this.operator == node.operator
Expand Down
1 change: 1 addition & 0 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -13236,6 +13236,7 @@ Compressor.prototype.compress = function(node) {
optional: self.optional,
expression: expr,
property: property,
quoted: true,
}).optimize(compressor);
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/minify.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ function minify(files, options) {
toplevel.mangle_names(options.mangle);
}
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.parse.expression) toplevel = toplevel.unwrap_expression();
if (timings) timings.output = Date.now();
Expand Down
2 changes: 1 addition & 1 deletion lib/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -1517,7 +1517,7 @@ function OutputStream(options) {
var expr = self.expression;
expr.print(output);
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("?.");
output.with_square(function() {
output.add_mapping(self.end);
Expand Down
2 changes: 2 additions & 0 deletions lib/propmangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ function reserve_quoted_keys(ast, reserved) {
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ClassProperty) {
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) {
if (node.start && node.start.quote) add(node.key);
} else if (node instanceof AST_Sub) {
Expand Down
4 changes: 3 additions & 1 deletion test/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,9 @@ function test_case(test) {
warnings_emitted.push(text);
}, /"INFO: /.test(expected_warnings));
}
var quoted_props;
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 = [];
test.mangle.properties.reserved = quoted_props;
U.reserve_quoted_keys(input, quoted_props);
Expand All @@ -323,6 +324,7 @@ function test_case(test) {
if (test.mangle) {
output.compute_char_frequency(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);
}
var output_code = make_code(output, output_options, test.expression);
Expand Down
71 changes: 68 additions & 3 deletions test/compress/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
beautify = {
ascii_only: true,
Expand Down Expand Up @@ -899,12 +961,15 @@ issue_2256: {
},
}
input: {
({ "keep": 1 });
g.keep = g.change;
({ "keep": 42 });
global.keep = global.change;
console.log(keep);
}
expect: {
g.keep = g.g;
global.keep = global.l;
console.log(keep);
}
expect_stdout: "undefined"
}

lhs_prop_1: {
Expand Down