extend the --define (global_defs) option by allowing dotted and square-bracket syntax

This commit is contained in:
Fábio Santos 2016-07-09 21:07:48 +01:00
parent 572b97b0bb
commit 23ec215401
3 changed files with 79 additions and 1 deletions

View File

@ -413,6 +413,9 @@ if (DEBUG) {
}
```
You can also define properties nested in other objects. For example,
`--define 'process.env["NODE_ENV"]="production"` also works.
UglifyJS will warn about the condition being always false and about dropping
unreachable code; for now there is no option to turn off only this specific
warning, you can pass `warnings=false` to turn off *all* warnings.
@ -448,7 +451,8 @@ uglifyJS.minify([ "input.js"], {
compress: {
dead_code: true,
global_defs: {
DEBUG: false
DEBUG: false,
"process.platform": "uglifyjs",
}
}
});

View File

@ -82,6 +82,20 @@ function Compressor(options, false_by_default) {
var sequences = this.options["sequences"];
this.sequences_limit = sequences == 1 ? 200 : sequences | 0;
this.warnings_produced = {};
var defines = this.options["global_defs"] || {};
var deep_definitions;
for (var key in defines) if (HOP(defines, key)) {
if (/[\.\[\s]/.test(key)) {
deep_definitions = deep_definitions || [];
var parsed = parse(key, { expression: true });
if (!(parsed instanceof AST_PropAccess)) {
throw new Error('Could not define ' + key);
}
deep_definitions.push([ parsed, defines[key] ]);
delete defines[key];
}
}
this.deep_definitions = deep_definitions;
};
Compressor.prototype = new TreeTransformer;
@ -2852,7 +2866,41 @@ merge(Compressor.prototype, {
return self;
});
function find_deep_global_definition(self, compressor) {
if (!compressor.deep_definitions) { return; }
for (var i = 0; i < compressor.deep_definitions.length; i++) {
if (find_deep(compressor.deep_definitions[i][0], self)) {
return make_node_from_constant(compressor, compressor.deep_definitions[i][1], self);
}
}
function find_deep(definition, node) {
if (node instanceof AST_SymbolRef || definition instanceof AST_SymbolRef) {
return (
node instanceof AST_SymbolRef &&
definition instanceof AST_SymbolRef &&
node.name === definition.name &&
node.undeclared()
);
}
if (
node instanceof AST_PropAccess &&
property_name(node.property) === property_name(definition.property)
) {
return find_deep(definition.expression, node.expression);
}
}
function property_name(property) {
if (typeof property === 'string') { return property; }
if (property instanceof AST_Constant) {
return String(property.getValue());
}
return {}; // Which is different from everything else
}
}
OPT(AST_Sub, function(self, compressor){
var statically_defined = find_deep_global_definition(self, compressor);
if (statically_defined) { return statically_defined; }
var prop = self.property;
if (prop instanceof AST_String && compressor.option("properties")) {
prop = prop.getValue();
@ -2873,6 +2921,8 @@ merge(Compressor.prototype, {
});
OPT(AST_Dot, function(self, compressor){
var statically_defined = find_deep_global_definition(self, compressor);
if (statically_defined) { return statically_defined; }
var prop = self.property;
if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) {
return make_node(AST_Sub, self, {

View File

@ -0,0 +1,24 @@
global_defs_works_deeply: {
options = {
global_defs: {
"foo.bar": false,
"window[1]": 0,
"foo.undef": undefined,
},
};
input: {
foo.bar;
foo["bar"];
window[1];
foo.undef;
}
expect: {
false;
false;
0;
void 0;
}
}