add keep_quoted=strict mode

This commit is contained in:
Andreas Svensson 2018-05-30 15:25:19 +02:00
parent efa21ae3e6
commit 6d47bf2e53
7 changed files with 105 additions and 11 deletions

View File

@ -807,6 +807,9 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix. Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names. - `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
- `true` -- quoted property names are reserved and any unquoted properties with the
same property name will not be mangled.
- `"strict"` -- advanced, all unquoted property names are mangled unless reserved.
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property - `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
names matching the regular expression. names matching the regular expression.

View File

@ -581,8 +581,11 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
} }
}); });
var AST_Dot = DEFNODE("Dot", null, { var AST_Dot = DEFNODE("Dot", "quote", {
$documentation: "A dotted property access expression", $documentation: "A dotted property access expression",
$propdoc: {
quote: "[string] the original quote character when transformed from AST_Sub",
},
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function(){
this.expression._walk(visitor); this.expression._walk(visitor);

View File

@ -6208,7 +6208,8 @@ merge(Compressor.prototype, {
&& property.length <= prop.print_to_string().length + 1) { && property.length <= prop.print_to_string().length + 1) {
return make_node(AST_Dot, self, { return make_node(AST_Dot, self, {
expression: expr, expression: expr,
property: property property: property,
quote: prop.quote,
}).optimize(compressor); }).optimize(compressor);
} }
} }

View File

@ -151,7 +151,7 @@ function minify(files, options) {
} }
toplevel = options.parse.toplevel; toplevel = options.parse.toplevel;
} }
if (quoted_props) { if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
reserve_quoted_keys(toplevel, quoted_props); reserve_quoted_keys(toplevel, quoted_props);
} }
if (options.wrap) { if (options.wrap) {

View File

@ -135,20 +135,30 @@ function mangle_properties(ast, options) {
var names_to_mangle = []; var names_to_mangle = [];
var unmangleable = []; var unmangleable = [];
var keep_quoted_strict = options.keep_quoted === "strict";
// step 1: find candidates to mangle // step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){ ast.walk(new TreeWalker(function(node){
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
add(node.key); if (!keep_quoted_strict || !node.quote) {
add(node.key);
}
} }
else if (node instanceof AST_ObjectProperty) { else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above // setter or getter, since KeyVal is handled above
add(node.key.name); if (!keep_quoted_strict || !node.key.start.quote) {
add(node.key.name);
}
} }
else if (node instanceof AST_Dot) { else if (node instanceof AST_Dot) {
add(node.property); if (!keep_quoted_strict || !node.quote) {
add(node.property);
}
} }
else if (node instanceof AST_Sub) { else if (node instanceof AST_Sub) {
addStrings(node.property, add); if (!keep_quoted_strict) {
addStrings(node.property, add);
}
} }
else if (node instanceof AST_Call else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") { && node.expression.print_to_string() == "Object.defineProperty") {
@ -159,14 +169,20 @@ function mangle_properties(ast, options) {
// step 2: transform the tree, renaming properties // step 2: transform the tree, renaming properties
return ast.transform(new TreeTransformer(function(node){ return ast.transform(new TreeTransformer(function(node){
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
node.key = mangle(node.key); if (!keep_quoted_strict || !node.quote) {
node.key = mangle(node.key);
}
} }
else if (node instanceof AST_ObjectProperty) { else if (node instanceof AST_ObjectProperty) {
// setter or getter // setter or getter
node.key.name = mangle(node.key.name); if (!keep_quoted_strict || !node.key.start.quote) {
node.key.name = mangle(node.key.name);
}
} }
else if (node instanceof AST_Dot) { else if (node instanceof AST_Dot) {
node.property = mangle(node.property); if (!keep_quoted_strict || !node.quote) {
node.property = mangle(node.property);
}
} }
else if (!options.keep_quoted && node instanceof AST_Sub) { else if (!options.keep_quoted && node instanceof AST_Sub) {
node.property = mangleStrings(node.property); node.property = mangleStrings(node.property);

View File

@ -0,0 +1,69 @@
keep_quoted_strict: {
options = {
evaluate: true,
properties: true,
},
mangle = {
properties: {
keep_quoted: "strict",
reserved: ["propc", "propd"],
},
}
input: {
var a = {
propa: 1,
get propb() { return 2; },
propc: 3,
get propd() { return 4; },
};
var b = {
"propa": 5,
get "propb"() { return 6; },
"propc": 7,
get "propd"() { return 8; },
};
var c = {};
Object.defineProperty(c, "propa", {"value": 9});
Object.defineProperty(c, "propc", {"value": 10});
console.log(a.propa, a.propb, a.propc, a["propc"], a.propd, a["propd"]);
console.log(b["propa"], b["propb"], b.propc, b["propc"], b.propd, b["propd"]);
console.log(c.propa, c["propc"]);
}
expect: {
var a = {
r: 1,
get p() {
return 2;
},
propc: 3,
get propd() {
return 4;
}
};
var b = {
propa: 5,
get propb() {
return 6;
},
propc: 7,
get propd() {
return 8;
}
};
var c = {};
Object.defineProperty(c, "r", {
value: 9
});
Object.defineProperty(c, "propc", {
value: 10
});
console.log(a.r, a.p, a.propc, a.propc, a.propd, a.propd);
console.log(b.propa, b.propb, b.propc, b.propc, b.propd, b.propd);
console.log(c.r, c.propc);
}
expect_stdout: [
"1 2 3 3 4 4",
"5 6 7 7 8 8",
"9 10",
]
}

View File

@ -114,7 +114,9 @@ function run_compress_tests() {
var quoted_props = test.mangle.properties.reserved; var 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); if (test.mangle.properties.keep_quoted !== "strict") {
U.reserve_quoted_keys(input, quoted_props);
}
} }
if (test.rename) { if (test.rename) {
input.figure_out_scope(test.mangle); input.figure_out_scope(test.mangle);