Handle uglify-reserve comments to reserve props

If you want uglify to reserve property names for a specific function, you
may now precede the function with comments containing:
uglify-reserve prop0 prop1 prop2 ... propN
and in that function's scope, these properties will not be mangled.

For example:

// uglify-reserve keepme
function foo() {
    return {
	keepme: "This property will NOT be mangled",
	butme: "This property WILL be mangled"
    };
}
This commit is contained in:
Zirak 2016-10-13 21:26:07 +00:00
parent 6389e52305
commit a9049497b1
2 changed files with 159 additions and 0 deletions

View File

@ -87,6 +87,7 @@ function mangle_properties(ast, options) {
var names_to_mangle = []; var names_to_mangle = [];
var unmangleable = []; var unmangleable = [];
var ignored = {}; var ignored = {};
var function_reserved = Object.create(null);
// step 1: find candidates to mangle // step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){ ast.walk(new TreeWalker(function(node){
@ -107,6 +108,15 @@ 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_Defun) {
function_reserved = Object.create(function_reserved);
var reserve_props = parse_reserve_comments(node.start.comments_before);
reserve_props.forEach(function(prop) {
function_reserved[prop] = true;
});
}
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
if (!(ignore_quoted && node.quote)) if (!(ignore_quoted && node.quote))
node.key = mangle(node.key); node.key = mangle(node.key);
@ -134,6 +144,10 @@ function mangle_properties(ast, options) {
// ); // );
// } // }
// } // }
}, function(node) {
if (node instanceof AST_Defun) {
function_reserved = Object.getPrototypeOf(function_reserved);
}
})); }));
// only function declarations after this line // only function declarations after this line
@ -152,6 +166,8 @@ function mangle_properties(ast, options) {
if (ignore_quoted && name in ignored) return false; if (ignore_quoted && name in ignored) return false;
if (regex && !regex.test(name)) return false; if (regex && !regex.test(name)) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
if (name in function_reserved) return false;
return cache.props.has(name) return cache.props.has(name)
|| names_to_mangle.indexOf(name) >= 0; || names_to_mangle.indexOf(name) >= 0;
} }
@ -227,4 +243,21 @@ function mangle_properties(ast, options) {
})); }));
} }
function parse_reserve_comments(comments) {
var props = [];
comments.forEach(function(comment) {
var text = comment.value;
var reserveRe = /^\s*uglify-reserve (.+)/gm,
match;
while (match = reserveRe.exec(text)) {
match[1].split(/\s+/).forEach(function(prop) {
push_uniq(props, prop);
});
}
});
return props;
}
} }

View File

@ -0,0 +1,126 @@
reserve_single_line: {
mangle_props = true
input: {
// noise
// uglify-reserve keepme andme
// noise
function foo() {
window.notme = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, butnotme: 0 };
}
// noise
// uglify-reserve keepme
//uglify-reserve andme
// noise
function bar() {
window.notme = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, butnotme: 0 };
}
}
expect: {
function foo() {
window.a = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, b: 0 };
}
function bar() {
window.a = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, b: 0 };
}
}
}
reserve_multi_line: {
mangle_props = true
input: {
/* uglify-reserve keepme andme*/
function foo() {
window.notme = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, butnotme: 0 };
}
/* noise
uglify-reserve keepme
uglify-reserve andme
noise */
function bar() {
window.notme = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, butnotme: 0 };
}
}
expect: {
function foo() {
window.a = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, b: 0 };
}
function bar() {
window.a = 0;
window.keepme = 1;
window["andme"] = 1;
return { andme: 1, "keepme": 1, b: 0 };
}
}
}
reserve_propagation: {
mangle_props = true
input: {
// uglify-reserve thisguy
function foo() {
// uglify-reserve thatguy
function bar() {
return {
notme: 0,
thisguy: 1,
thatguy: 1
};
}
return {
whome: 0,
thisguy: 1,
thatguy: 0
};
}
var o = {
whome: 0,
thisguy: 0,
thatguy: 0
};
}
expect: {
function foo() {
function bar() {
return {
a: 0,
thisguy: 1,
thatguy: 1
};
}
return {
b: 0,
thisguy: 1,
c: 0
};
}
var o = {
b: 0,
d: 0,
c: 0
};
}
}