This commit is contained in:
Fábio Santos 2018-03-19 16:46:27 +00:00 committed by GitHub
commit a6c7f8d19e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 1 deletions

View File

@ -110,6 +110,8 @@ a double dash to prevent input files being used as option arguments:
--keep-classnames Do not mangle/drop class names. --keep-classnames Do not mangle/drop class names.
--keep-fnames Do not mangle/drop function names. Useful for --keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name. code relying on Function.prototype.name.
--module Input is an ES6 module. If `compress` or `mangle` is
enabled then the `toplevel` option will be enabled.
--name-cache <file> File to hold mangled name mappings. --name-cache <file> File to hold mangled name mappings.
--safari10 Support non-standard Safari 10/11. --safari10 Support non-standard Safari 10/11.
Equivalent to setting `safari10: true` in `minify()` Equivalent to setting `safari10: true` in `minify()`
@ -496,6 +498,10 @@ if (result.error) throw result.error;
- `mangle.properties` (default `false`) — a subcategory of the mangle option. - `mangle.properties` (default `false`) — a subcategory of the mangle option.
Pass an object to specify custom [mangle property options](#mangle-properties-options). Pass an object to specify custom [mangle property options](#mangle-properties-options).
- `module` (default `false`) — Use when minifying an ES6 module. "use strict"
is implied and names can be mangled on the top scope. If `compress` or
`mangle` is enabled then the `toplevel` option will be enabled.
- `output` (default `null`) — pass an object if you wish to specify - `output` (default `null`) — pass an object if you wish to specify
additional [output options](#output-options). The defaults are optimized additional [output options](#output-options). The defaults are optimized
for best compression. for best compression.
@ -554,6 +560,7 @@ if (result.error) throw result.error;
keep_classnames: false, keep_classnames: false,
keep_fnames: false, keep_fnames: false,
ie8: false, ie8: false,
module: false,
nameCache: null, // or specify a name cache object nameCache: null, // or specify a name cache object
safari10: false, safari10: false,
toplevel: false, toplevel: false,
@ -702,6 +709,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops - `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
when we can statically determine the condition. when we can statically determine the condition.
- `module` (default `false`) -- Pass `true` when compressing an ES6 module. Strict
mode is implied and the `toplevel` option as well.
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions" - `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parens that the where the return value is discarded, to avoid the parens that the
code generator would insert. code generator would insert.
@ -823,6 +833,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames` Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
[compress option](#compress-options). [compress option](#compress-options).
- `module` (default `false`) -- Pass `true` an ES6 modules, where the toplevel
scope is not the global scope. Implies `toplevel`.
- `reserved` (default `[]`) -- Pass an array of identifiers that should be - `reserved` (default `[]`) -- Pass an array of identifiers that should be
excluded from mangling. Example: `["foo", "bar"]`. excluded from mangling. Example: `["foo", "bar"]`.

View File

@ -44,6 +44,7 @@ program.option("--ecma <version>", "Specify ECMAScript release: 5, 6, 7 or 8.");
program.option("--ie8", "Support non-standard Internet Explorer 8."); program.option("--ie8", "Support non-standard Internet Explorer 8.");
program.option("--keep-classnames", "Do not mangle/drop class names."); program.option("--keep-classnames", "Do not mangle/drop class names.");
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name."); program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
program.option("--module", "Input is an ES6 module");
program.option("--name-cache <file>", "File to hold mangled name mappings."); program.option("--name-cache <file>", "File to hold mangled name mappings.");
program.option("--rename", "Force symbol expansion."); program.option("--rename", "Force symbol expansion.");
program.option("--no-rename", "Disable symbol expansion."); program.option("--no-rename", "Disable symbol expansion.");
@ -66,6 +67,7 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
"compress", "compress",
"ie8", "ie8",
"mangle", "mangle",
"module",
"safari10", "safari10",
"sourceMap", "sourceMap",
"toplevel", "toplevel",
@ -195,7 +197,8 @@ function run() {
return require("acorn").parse(files[name], { return require("acorn").parse(files[name], {
locations: true, locations: true,
program: toplevel, program: toplevel,
sourceFile: name sourceFile: name,
sourceType: options.module || program.parse.module ? "module" : "script"
}); });
}); });
} else if (program.parse.spidermonkey) { } else if (program.parse.spidermonkey) {

View File

@ -73,6 +73,7 @@ function Compressor(options, false_by_default) {
keep_fnames : false, keep_fnames : false,
keep_infinity : false, keep_infinity : false,
loops : !false_by_default, loops : !false_by_default,
module : false,
negate_iife : !false_by_default, negate_iife : !false_by_default,
passes : 1, passes : 1,
properties : !false_by_default, properties : !false_by_default,
@ -130,6 +131,10 @@ function Compressor(options, false_by_default) {
return top_retain.indexOf(def.name) >= 0; return top_retain.indexOf(def.name) >= 0;
}; };
} }
if (this.options["module"]) {
this.directives["use strict"] = true;
this.options["toplevel"] = true;
}
var toplevel = this.options["toplevel"]; var toplevel = this.options["toplevel"];
this.toplevel = typeof toplevel == "string" ? { this.toplevel = typeof toplevel == "string" ? {
funcs: /funcs/.test(toplevel), funcs: /funcs/.test(toplevel),

View File

@ -52,6 +52,7 @@ function minify(files, options) {
keep_classnames: undefined, keep_classnames: undefined,
keep_fnames: false, keep_fnames: false,
mangle: {}, mangle: {},
module: false,
nameCache: null, nameCache: null,
output: {}, output: {},
parse: {}, parse: {},
@ -76,6 +77,7 @@ function minify(files, options) {
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]); set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_classnames", options, [ "compress", "mangle" ]); set_shorthand("keep_classnames", options, [ "compress", "mangle" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]); set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("module", options, [ "parse", "compress", "mangle" ]);
set_shorthand("safari10", options, [ "mangle", "output" ]); set_shorthand("safari10", options, [ "mangle", "output" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]); set_shorthand("toplevel", options, [ "compress", "mangle" ]);
set_shorthand("warnings", options, [ "compress" ]); set_shorthand("warnings", options, [ "compress" ]);
@ -87,6 +89,7 @@ function minify(files, options) {
ie8: false, ie8: false,
keep_classnames: false, keep_classnames: false,
keep_fnames: false, keep_fnames: false,
module: false,
properties: false, properties: false,
reserved: [], reserved: [],
safari10: false, safari10: false,

View File

@ -859,6 +859,7 @@ function parse($TEXT, options) {
expression : false, expression : false,
filename : null, filename : null,
html5_comments : true, html5_comments : true,
module : false,
shebang : true, shebang : true,
strict : false, strict : false,
toplevel : null, toplevel : null,
@ -2913,6 +2914,7 @@ function parse($TEXT, options) {
var start = S.token; var start = S.token;
var body = []; var body = [];
S.input.push_directives_stack(); S.input.push_directives_stack();
if (options.module) S.input.add_directive("use strict");
while (!is("eof")) while (!is("eof"))
body.push(statement()); body.push(statement());
S.input.pop_directives_stack(); S.input.pop_directives_stack();

View File

@ -514,9 +514,13 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
ie8 : false, ie8 : false,
keep_classnames: false, keep_classnames: false,
keep_fnames : false, keep_fnames : false,
module : false,
reserved : [], reserved : [],
toplevel : false, toplevel : false,
}); });
if (options["module"]) {
options.toplevel = true;
}
if (!Array.isArray(options.reserved)) options.reserved = []; if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments // Never mangle arguments
push_uniq(options.reserved, "arguments"); push_uniq(options.reserved, "arguments");

View File

@ -1601,3 +1601,52 @@ issue_2874_3: {
] ]
node_version: ">=6" node_version: ">=6"
} }
module_enables_strict_mode: {
options = {
module: true,
}
input: {
if (1) {
function xyz() {}
}
}
expect: {
if (1) {
function xyz() {}
}
}
}
module_mangle_scope: {
mangle = {
module: true
}
input: {
let a = 10;
}
expect: {
let e = 10;
}
}
module_enabled: {
options = {
module: true,
reduce_vars: true,
unused: true,
}
mangle = {
module: true,
}
input: {
let apple = 10, b = 20;
console.log(apple++, b, apple++);
export { apple };
}
expect: {
let o = 10;
console.log(o++, 20, o++);
export { o as apple };
}
}

View File

@ -0,0 +1,2 @@
let foo = 1, bar = 2;
export { foo };

View File

@ -734,6 +734,15 @@ describe("bin/uglifyjs", function () {
done(); done();
}); });
}); });
it("Should mangle toplevel names with the --module option", function(done) {
var command = uglifyjscmd + " test/input/module/input.js --module -mc";
exec(command, function (err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "let e=1;export{e as foo};\n")
done();
});
});
it("Should fail with --define a-b", function(done) { it("Should fail with --define a-b", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b"; var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
exec(command, function (err, stdout, stderr) { exec(command, function (err, stdout, stderr) {