Repository: webpack-contrib/uglifyjs-webpack-plugin
Pull request #229 (2018-02-09 11:20:48)

feat(minify): add missing `toplevel`, `nameCache`, `keep_classnames`, `keep_fnames` and `safari10` options (`uglifyOptions`)
<!--
1. [Read and sign the CLA](https://cla.js.foundation/webpack/webpack.js.org). This needs to be done only once. PRs that haven't signed it won't be accepted.
2. Check out the [development guide](https://webpack.js.org/development/) for the API and development guidelines.
3. Read through the PR diff carefully as sometimes this can reveal issues. The work will be reviewed, but this can save some effort.
-->
Also sort options as uglify docs.

Add all options and tests. In next PR i try to implement internal cache for `nameCache` for increase perf :+1: 

evilebottnawi: @michael-ciniawsky done :+1: 

Patch:
diff --git a/README.md b/README.md
index 953974d..88b6fc0 100644
--- a/README.md
+++ b/README.md
@@ -160,22 +160,28 @@ Number of concurrent runs.
 
 |Name|Type|Default|Description|
 |:--:|:--:|:-----:|:----------|
-|**`ie8`**|`{Boolean}`|`false`|Enable IE8 Support|
 |**`ecma`**|`{Number}`|`undefined`|Supported ECMAScript Version (`5`, `6`, `7` or `8`). Affects `parse`, `compress` && `output` options|
+|**`warnings`**|`{Boolean}`|`false`|Display Warnings|
 |**[`parse`](https://github.com/mishoo/UglifyJS2/tree/harmony#parse-options)**|`{Object}`|`{}`|Additional Parse Options|
+|**[`compress`](https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options)**|`{Boolean\|Object}`|`true`|Additional Compress Options|
 |**[`mangle`](https://github.com/mishoo/UglifyJS2/tree/harmony#mangle-options)**|`{Boolean\|Object}`|`true`|Enable Name Mangling (See [Mangle Properties](https://github.com/mishoo/UglifyJS2/tree/harmony#mangle-properties-options) for advanced setups, use with ⚠️)|
 |**[`output`](https://github.com/mishoo/UglifyJS2/tree/harmony#output-options)**|`{Object}`|`{}`|Additional Output Options (The defaults are optimized for best compression)|
-|**[`compress`](https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options)**|`{Boolean\|Object}`|`true`|Additional Compress Options|
-|**`warnings`**|`{Boolean}`|`false`|Display Warnings|
+|**`toplevel`**|`{Boolean}`|`false`|Enable top level variable and function name mangling and to drop unused variables and functions|
+|**`nameCache`**|`{Object}`|`null`|Enable cache of mangled variable and property names across multiple invocations|
+|**`ie8`**|`{Boolean}`|`false`|Enable IE8 Support|
+|**`keep_classnames`**|`{Boolean}`|`undefined`|Enable prevent discarding or mangling of class names|
+|**`keep_fnames`**|`{Boolean}`|`false`| Enable prevent discarding or mangling of function names. Useful for code relying on `Function.prototype.name`. If the top level minify option `keep_classnames` is `undefined` it will be overriden with the value of the top level minify option `keep_fnames`|
+|**`safari10`**|`{Boolean}`|`false`|Enable work around Safari 10/11 bugs in loop scoping and `await`|
 
 **webpack.config.js**
 ```js
 [
   new UglifyJsPlugin({
     uglifyOptions: {
-      ie8: false,
       ecma: 8,
+      warnings: false,
       parse: {...options},
+      compress: {...options},
       mangle: {
         ...options,
         properties: {
@@ -187,8 +193,12 @@ Number of concurrent runs.
         beautify: false,
         ...options
       },
-      compress: {...options},
-      warnings: false
+      toplevel: false,
+      nameCache: null,
+      ie8: false,
+      keep_classnames: undefined,
+      keep_fnames: false,
+      safari10: false,
     }
   })
 ]
diff --git a/src/uglify/minify.js b/src/uglify/minify.js
index 4bdbffb..94f7e1b 100644
--- a/src/uglify/minify.js
+++ b/src/uglify/minify.js
@@ -4,19 +4,25 @@
 import uglify from 'uglify-es';
 
 const buildUglifyOptions = ({
-  ie8,
   ecma,
+  warnings,
   parse = {},
+  compress = {},
   mangle,
   output,
-  compress = {},
-  warnings,
   toplevel,
   nameCache,
-} = {}) => ({
   ie8,
+  /* eslint-disable camelcase */
+  keep_classnames,
+  keep_fnames,
+  /* eslint-enable camelcase */
+  safari10,
+} = {}) => ({
   ecma,
+  warnings,
   parse,
+  compress,
   mangle: mangle == null ? true : mangle,
   output: {
     shebang: true,
@@ -25,12 +31,14 @@ const buildUglifyOptions = ({
     semicolons: true,
     ...output,
   },
-  compress,
-  warnings,
-  toplevel,
-  nameCache,
   // Ignoring sourcemap from options
   sourceMap: null,
+  toplevel,
+  nameCache,
+  ie8,
+  keep_classnames,
+  keep_fnames,
+  safari10,
 });
 
 const buildComments = (options, uglifyOptions, extractedComments) => {


Test patch:
diff --git a/test/__snapshots__/uglify-options.test.js.snap b/test/__snapshots__/uglify-options.test.js.snap
new file mode 100644
index 0000000..819d4bb
--- /dev/null
+++ b/test/__snapshots__/uglify-options.test.js.snap
@@ -0,0 +1,476 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`import-export: errors 1`] = `Array []`;
+
+exports[`import-export: errors 2`] = `Array []`;
+
+exports[`import-export: errors 3`] = `Array []`;
+
+exports[`import-export: errors 4`] = `Array []`;
+
+exports[`import-export: errors 5`] = `Array []`;
+
+exports[`import-export: main.js 1`] = `
+"webpackJsonp([ 0 ], [ function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    Object.defineProperty(__webpack_exports__, \\"__esModule\\", {
+        value: !0
+    });
+    var __WEBPACK_IMPORTED_MODULE_0__dep__ = __webpack_require__(1);
+    __webpack_exports__.default = function() {
+        const b = __WEBPACK_IMPORTED_MODULE_0__dep__.b, baz = \`baz\${Math.random()}\`;
+        return () => ({
+            a: b + __WEBPACK_IMPORTED_MODULE_0__dep__.a + baz,
+            b: b,
+            baz: baz
+        });
+    };
+}, function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    __webpack_exports__.a = \\"bar\\", __webpack_exports__.b = \\"foo\\";
+} ], [ 0 ]);"
+`;
+
+exports[`import-export: main.js 2`] = `
+"webpackJsonp([ 0 ], [ function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    Object.defineProperty(__webpack_exports__, \\"__esModule\\", {
+        value: !0
+    });
+    var __WEBPACK_IMPORTED_MODULE_0__dep__ = __webpack_require__(1);
+    __webpack_exports__.default = function() {
+        const b = __WEBPACK_IMPORTED_MODULE_0__dep__.b, baz = \`baz\${Math.random()}\`;
+        return () => ({
+            a: b + __WEBPACK_IMPORTED_MODULE_0__dep__.a + baz,
+            b: b,
+            baz: baz
+        });
+    };
+}, function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    __webpack_exports__.a = \\"bar\\", __webpack_exports__.b = \\"foo\\";
+} ], [ 0 ]);"
+`;
+
+exports[`import-export: main.js 3`] = `
+"webpackJsonp([ 0 ], [ function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    Object.defineProperty(__webpack_exports__, \\"__esModule\\", {
+        value: !0
+    });
+    var __WEBPACK_IMPORTED_MODULE_0__dep__ = __webpack_require__(1);
+    __webpack_exports__.default = function() {
+        const b = __WEBPACK_IMPORTED_MODULE_0__dep__.b, baz = \`baz\${Math.random()}\`;
+        return () => ({
+            a: b + __WEBPACK_IMPORTED_MODULE_0__dep__.a + baz,
+            b: b,
+            baz: baz
+        });
+    };
+}, function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    __webpack_exports__.a = \\"bar\\", __webpack_exports__.b = \\"foo\\";
+} ], [ 0 ]);"
+`;
+
+exports[`import-export: main.js 4`] = `
+"webpackJsonp([ 0 ], [ function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    Object.defineProperty(__webpack_exports__, \\"__esModule\\", {
+        value: !0
+    });
+    var __WEBPACK_IMPORTED_MODULE_0__dep__ = __webpack_require__(1);
+    __webpack_exports__.default = function Foo() {
+        const b = __WEBPACK_IMPORTED_MODULE_0__dep__.b, baz = \`baz\${Math.random()}\`;
+        return () => ({
+            a: b + __WEBPACK_IMPORTED_MODULE_0__dep__.a + baz,
+            b: b,
+            baz: baz
+        });
+    };
+}, function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    __webpack_exports__.a = \\"bar\\", __webpack_exports__.b = \\"foo\\";
+} ], [ 0 ]);"
+`;
+
+exports[`import-export: main.js 5`] = `
+"webpackJsonp([ 0 ], [ function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    Object.defineProperty(__webpack_exports__, \\"__esModule\\", {
+        value: !0
+    });
+    var __WEBPACK_IMPORTED_MODULE_0__dep__ = __webpack_require__(1);
+    __webpack_exports__.default = function() {
+        const b = __WEBPACK_IMPORTED_MODULE_0__dep__.b, baz = \`baz\${Math.random()}\`;
+        return () => ({
+            a: b + __WEBPACK_IMPORTED_MODULE_0__dep__.a + baz,
+            b: b,
+            baz: baz
+        });
+    };
+}, function(module, __webpack_exports__, __webpack_require__) {
+    \\"use strict\\";
+    __webpack_exports__.a = \\"bar\\", __webpack_exports__.b = \\"foo\\";
+} ], [ 0 ]);"
+`;
+
+exports[`import-export: manifest.js 1`] = `
+"!function(modules) {
+    var parentJsonpFunction = window.webpackJsonp;
+    window.webpackJsonp = function(chunkIds, moreModules, executeModules) {
+        for (var moduleId, chunkId, result, i = 0, resolves = []; i < chunkIds.length; i++) chunkId = chunkIds[i], 
+        installedChunks[chunkId] && resolves.push(installedChunks[chunkId][0]), installedChunks[chunkId] = 0;
+        for (moduleId in moreModules) Object.prototype.hasOwnProperty.call(moreModules, moduleId) && (modules[moduleId] = moreModules[moduleId]);
+        for (parentJsonpFunction && parentJsonpFunction(chunkIds, moreModules, executeModules); resolves.length; ) resolves.shift()();
+        if (executeModules) for (i = 0; i < executeModules.length; i++) result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+        return result;
+    };
+    var installedModules = {}, installedChunks = {
+        1: 0
+    };
+    function __webpack_require__(moduleId) {
+        if (installedModules[moduleId]) return installedModules[moduleId].exports;
+        var module = installedModules[moduleId] = {
+            i: moduleId,
+            l: !1,
+            exports: {}
+        };
+        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
+        module.l = !0, module.exports;
+    }
+    __webpack_require__.e = function(chunkId) {
+        var installedChunkData = installedChunks[chunkId];
+        if (0 === installedChunkData) return new Promise(function(resolve) {
+            resolve();
+        });
+        if (installedChunkData) return installedChunkData[2];
+        var promise = new Promise(function(resolve, reject) {
+            installedChunkData = installedChunks[chunkId] = [ resolve, reject ];
+        });
+        installedChunkData[2] = promise;
+        var head = document.getElementsByTagName(\\"head\\")[0], script = document.createElement(\\"script\\");
+        script.type = \\"text/javascript\\", script.charset = \\"utf-8\\", script.async = !0, script.timeout = 12e4, 
+        __webpack_require__.nc && script.setAttribute(\\"nonce\\", __webpack_require__.nc), 
+        script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({
+            0: \\"main\\"
+        }[chunkId] || chunkId) + \\".js\\";
+        var timeout = setTimeout(onScriptComplete, 12e4);
+        function onScriptComplete() {
+            script.onerror = script.onload = null, clearTimeout(timeout);
+            var chunk = installedChunks[chunkId];
+            0 !== chunk && (chunk && chunk[1](new Error(\\"Loading chunk \\" + chunkId + \\" failed.\\")), 
+            installedChunks[chunkId] = void 0);
+        }
+        return script.onerror = script.onload = onScriptComplete, head.appendChild(script), 
+        promise;
+    }, __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
+        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
+            configurable: !1,
+            enumerable: !0,
+            get: getter
+        });
+    }, __webpack_require__.n = function(module) {
+        var getter = module && module.__esModule ? function() {
+            return module.default;
+        } : function() {
+            return module;
+        };
+        return __webpack_require__.d(getter, \\"a\\", getter), getter;
+    }, __webpack_require__.o = function(object, property) {
+        return Object.prototype.hasOwnProperty.call(object, property);
+    }, __webpack_require__.p = \\"\\", __webpack_require__.oe = function(err) {
+        throw console.error(err), err;
+    };
+}([]);"
+`;
+
+exports[`import-export: manifest.js 2`] = `
+"!function(modules) {
+    var parentJsonpFunction = window.webpackJsonp;
+    window.webpackJsonp = function(chunkIds, moreModules, executeModules) {
+        for (var moduleId, chunkId, result, i = 0, resolves = []; i < chunkIds.length; i++) chunkId = chunkIds[i], 
+        installedChunks[chunkId] && resolves.push(installedChunks[chunkId][0]), installedChunks[chunkId] = 0;
+        for (moduleId in moreModules) Object.prototype.hasOwnProperty.call(moreModules, moduleId) && (modules[moduleId] = moreModules[moduleId]);
+        for (parentJsonpFunction && parentJsonpFunction(chunkIds, moreModules, executeModules); resolves.length; ) resolves.shift()();
+        if (executeModules) for (i = 0; i < executeModules.length; i++) result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+        return result;
+    };
+    var installedModules = {}, installedChunks = {
+        1: 0
+    };
+    function __webpack_require__(moduleId) {
+        if (installedModules[moduleId]) return installedModules[moduleId].exports;
+        var module = installedModules[moduleId] = {
+            i: moduleId,
+            l: !1,
+            exports: {}
+        };
+        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
+        module.l = !0, module.exports;
+    }
+    __webpack_require__.e = function(chunkId) {
+        var installedChunkData = installedChunks[chunkId];
+        if (0 === installedChunkData) return new Promise(function(resolve) {
+            resolve();
+        });
+        if (installedChunkData) return installedChunkData[2];
+        var promise = new Promise(function(resolve, reject) {
+            installedChunkData = installedChunks[chunkId] = [ resolve, reject ];
+        });
+        installedChunkData[2] = promise;
+        var head = document.getElementsByTagName(\\"head\\")[0], script = document.createElement(\\"script\\");
+        script.type = \\"text/javascript\\", script.charset = \\"utf-8\\", script.async = !0, script.timeout = 12e4, 
+        __webpack_require__.nc && script.setAttribute(\\"nonce\\", __webpack_require__.nc), 
+        script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({
+            0: \\"main\\"
+        }[chunkId] || chunkId) + \\".js\\";
+        var timeout = setTimeout(onScriptComplete, 12e4);
+        function onScriptComplete() {
+            script.onerror = script.onload = null, clearTimeout(timeout);
+            var chunk = installedChunks[chunkId];
+            0 !== chunk && (chunk && chunk[1](new Error(\\"Loading chunk \\" + chunkId + \\" failed.\\")), 
+            installedChunks[chunkId] = void 0);
+        }
+        return script.onerror = script.onload = onScriptComplete, head.appendChild(script), 
+        promise;
+    }, __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
+        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
+            configurable: !1,
+            enumerable: !0,
+            get: getter
+        });
+    }, __webpack_require__.n = function(module) {
+        var getter = module && module.__esModule ? function() {
+            return module.default;
+        } : function() {
+            return module;
+        };
+        return __webpack_require__.d(getter, \\"a\\", getter), getter;
+    }, __webpack_require__.o = function(object, property) {
+        return Object.prototype.hasOwnProperty.call(object, property);
+    }, __webpack_require__.p = \\"\\", __webpack_require__.oe = function(err) {
+        throw console.error(err), err;
+    };
+}([]);"
+`;
+
+exports[`import-export: manifest.js 3`] = `
+"!function(modules) {
+    var parentJsonpFunction = window.webpackJsonp;
+    window.webpackJsonp = function(chunkIds, moreModules, executeModules) {
+        for (var moduleId, chunkId, result, i = 0, resolves = []; i < chunkIds.length; i++) chunkId = chunkIds[i], 
+        installedChunks[chunkId] && resolves.push(installedChunks[chunkId][0]), installedChunks[chunkId] = 0;
+        for (moduleId in moreModules) Object.prototype.hasOwnProperty.call(moreModules, moduleId) && (modules[moduleId] = moreModules[moduleId]);
+        for (parentJsonpFunction && parentJsonpFunction(chunkIds, moreModules, executeModules); resolves.length; ) resolves.shift()();
+        if (executeModules) for (i = 0; i < executeModules.length; i++) result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+        return result;
+    };
+    var installedModules = {}, installedChunks = {
+        1: 0
+    };
+    function __webpack_require__(moduleId) {
+        if (installedModules[moduleId]) return installedModules[moduleId].exports;
+        var module = installedModules[moduleId] = {
+            i: moduleId,
+            l: !1,
+            exports: {}
+        };
+        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
+        module.l = !0, module.exports;
+    }
+    __webpack_require__.e = function(chunkId) {
+        var installedChunkData = installedChunks[chunkId];
+        if (0 === installedChunkData) return new Promise(function(resolve) {
+            resolve();
+        });
+        if (installedChunkData) return installedChunkData[2];
+        var promise = new Promise(function(resolve, reject) {
+            installedChunkData = installedChunks[chunkId] = [ resolve, reject ];
+        });
+        installedChunkData[2] = promise;
+        var head = document.getElementsByTagName(\\"head\\")[0], script = document.createElement(\\"script\\");
+        script.type = \\"text/javascript\\", script.charset = \\"utf-8\\", script.async = !0, script.timeout = 12e4, 
+        __webpack_require__.nc && script.setAttribute(\\"nonce\\", __webpack_require__.nc), 
+        script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({
+            0: \\"main\\"
+        }[chunkId] || chunkId) + \\".js\\";
+        var timeout = setTimeout(onScriptComplete, 12e4);
+        function onScriptComplete() {
+            script.onerror = script.onload = null, clearTimeout(timeout);
+            var chunk = installedChunks[chunkId];
+            0 !== chunk && (chunk && chunk[1](new Error(\\"Loading chunk \\" + chunkId + \\" failed.\\")), 
+            installedChunks[chunkId] = void 0);
+        }
+        return script.onerror = script.onload = onScriptComplete, head.appendChild(script), 
+        promise;
+    }, __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
+        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
+            configurable: !1,
+            enumerable: !0,
+            get: getter
+        });
+    }, __webpack_require__.n = function(module) {
+        var getter = module && module.__esModule ? function() {
+            return module.default;
+        } : function() {
+            return module;
+        };
+        return __webpack_require__.d(getter, \\"a\\", getter), getter;
+    }, __webpack_require__.o = function(object, property) {
+        return Object.prototype.hasOwnProperty.call(object, property);
+    }, __webpack_require__.p = \\"\\", __webpack_require__.oe = function(err) {
+        throw console.error(err), err;
+    };
+}([]);"
+`;
+
+exports[`import-export: manifest.js 4`] = `
+"!function(modules) {
+    var parentJsonpFunction = window.webpackJsonp;
+    window.webpackJsonp = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
+        for (var moduleId, chunkId, result, i = 0, resolves = []; i < chunkIds.length; i++) chunkId = chunkIds[i], 
+        installedChunks[chunkId] && resolves.push(installedChunks[chunkId][0]), installedChunks[chunkId] = 0;
+        for (moduleId in moreModules) Object.prototype.hasOwnProperty.call(moreModules, moduleId) && (modules[moduleId] = moreModules[moduleId]);
+        for (parentJsonpFunction && parentJsonpFunction(chunkIds, moreModules, executeModules); resolves.length; ) resolves.shift()();
+        if (executeModules) for (i = 0; i < executeModules.length; i++) result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+        return result;
+    };
+    var installedModules = {}, installedChunks = {
+        1: 0
+    };
+    function __webpack_require__(moduleId) {
+        if (installedModules[moduleId]) return installedModules[moduleId].exports;
+        var module = installedModules[moduleId] = {
+            i: moduleId,
+            l: !1,
+            exports: {}
+        };
+        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
+        module.l = !0, module.exports;
+    }
+    __webpack_require__.e = function requireEnsure(chunkId) {
+        var installedChunkData = installedChunks[chunkId];
+        if (0 === installedChunkData) return new Promise(function(resolve) {
+            resolve();
+        });
+        if (installedChunkData) return installedChunkData[2];
+        var promise = new Promise(function(resolve, reject) {
+            installedChunkData = installedChunks[chunkId] = [ resolve, reject ];
+        });
+        installedChunkData[2] = promise;
+        var head = document.getElementsByTagName(\\"head\\")[0], script = document.createElement(\\"script\\");
+        script.type = \\"text/javascript\\", script.charset = \\"utf-8\\", script.async = !0, script.timeout = 12e4, 
+        __webpack_require__.nc && script.setAttribute(\\"nonce\\", __webpack_require__.nc), 
+        script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({
+            0: \\"main\\"
+        }[chunkId] || chunkId) + \\".js\\";
+        var timeout = setTimeout(onScriptComplete, 12e4);
+        function onScriptComplete() {
+            script.onerror = script.onload = null, clearTimeout(timeout);
+            var chunk = installedChunks[chunkId];
+            0 !== chunk && (chunk && chunk[1](new Error(\\"Loading chunk \\" + chunkId + \\" failed.\\")), 
+            installedChunks[chunkId] = void 0);
+        }
+        return script.onerror = script.onload = onScriptComplete, head.appendChild(script), 
+        promise;
+    }, __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
+        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
+            configurable: !1,
+            enumerable: !0,
+            get: getter
+        });
+    }, __webpack_require__.n = function(module) {
+        var getter = module && module.__esModule ? function getDefault() {
+            return module.default;
+        } : function getModuleExports() {
+            return module;
+        };
+        return __webpack_require__.d(getter, \\"a\\", getter), getter;
+    }, __webpack_require__.o = function(object, property) {
+        return Object.prototype.hasOwnProperty.call(object, property);
+    }, __webpack_require__.p = \\"\\", __webpack_require__.oe = function(err) {
+        throw console.error(err), err;
+    };
+}([]);"
+`;
+
+exports[`import-export: manifest.js 5`] = `
+"!function(modules) {
+    var parentJsonpFunction = window.webpackJsonp;
+    window.webpackJsonp = function(chunkIds, moreModules, executeModules) {
+        for (var moduleId, chunkId, result, i = 0, resolves = []; i < chunkIds.length; i++) chunkId = chunkIds[i], 
+        installedChunks[chunkId] && resolves.push(installedChunks[chunkId][0]), installedChunks[chunkId] = 0;
+        for (moduleId in moreModules) Object.prototype.hasOwnProperty.call(moreModules, moduleId) && (modules[moduleId] = moreModules[moduleId]);
+        for (parentJsonpFunction && parentJsonpFunction(chunkIds, moreModules, executeModules); resolves.length; ) resolves.shift()();
+        if (executeModules) for (i = 0; i < executeModules.length; i++) result = __webpack_require__(__webpack_require__.s = executeModules[i]);
+        return result;
+    };
+    var installedModules = {}, installedChunks = {
+        1: 0
+    };
+    function __webpack_require__(moduleId) {
+        if (installedModules[moduleId]) return installedModules[moduleId].exports;
+        var module = installedModules[moduleId] = {
+            i: moduleId,
+            l: !1,
+            exports: {}
+        };
+        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
+        module.l = !0, module.exports;
+    }
+    __webpack_require__.e = function(chunkId) {
+        var installedChunkData = installedChunks[chunkId];
+        if (0 === installedChunkData) return new Promise(function(resolve) {
+            resolve();
+        });
+        if (installedChunkData) return installedChunkData[2];
+        var promise = new Promise(function(resolve, reject) {
+            installedChunkData = installedChunks[chunkId] = [ resolve, reject ];
+        });
+        installedChunkData[2] = promise;
+        var head = document.getElementsByTagName(\\"head\\")[0], script = document.createElement(\\"script\\");
+        script.type = \\"text/javascript\\", script.charset = \\"utf-8\\", script.async = !0, script.timeout = 12e4, 
+        __webpack_require__.nc && script.setAttribute(\\"nonce\\", __webpack_require__.nc), 
+        script.src = __webpack_require__.p + \\"\\" + chunkId + \\".\\" + ({
+            0: \\"main\\"
+        }[chunkId] || chunkId) + \\".js\\";
+        var timeout = setTimeout(onScriptComplete, 12e4);
+        function onScriptComplete() {
+            script.onerror = script.onload = null, clearTimeout(timeout);
+            var chunk = installedChunks[chunkId];
+            0 !== chunk && (chunk && chunk[1](new Error(\\"Loading chunk \\" + chunkId + \\" failed.\\")), 
+            installedChunks[chunkId] = void 0);
+        }
+        return script.onerror = script.onload = onScriptComplete, head.appendChild(script), 
+        promise;
+    }, __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
+        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
+            configurable: !1,
+            enumerable: !0,
+            get: getter
+        });
+    }, __webpack_require__.n = function(module) {
+        var getter = module && module.__esModule ? function() {
+            return module.default;
+        } : function() {
+            return module;
+        };
+        return __webpack_require__.d(getter, \\"a\\", getter), getter;
+    }, __webpack_require__.o = function(object, property) {
+        return Object.prototype.hasOwnProperty.call(object, property);
+    }, __webpack_require__.p = \\"\\", __webpack_require__.oe = function(err) {
+        throw console.error(err), err;
+    };
+}([]);"
+`;
+
+exports[`import-export: warnings 1`] = `Array []`;
+
+exports[`import-export: warnings 2`] = `Array []`;
+
+exports[`import-export: warnings 3`] = `Array []`;
+
+exports[`import-export: warnings 4`] = `Array []`;
+
+exports[`import-export: warnings 5`] = `Array []`;
diff --git a/test/uglify-options.test.js b/test/uglify-options.test.js
new file mode 100644
index 0000000..8ee299c
--- /dev/null
+++ b/test/uglify-options.test.js
@@ -0,0 +1,188 @@
+import UglifyJsPlugin from '../src/index';
+import {
+  cleanErrorStack,
+  createCompiler,
+  compile,
+} from './helpers';
+
+describe('when applied with uglify-es options', () => {
+  it('matches snapshot for `toplevel` option', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/import-export/entry.js`,
+      output: {
+        path: `${__dirname}/dist-import-export`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        toplevel: true,
+        mangle: false,
+        warnings: true,
+        output: {
+          beautify: true,
+        },
+      },
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('import-export: errors');
+      expect(warnings).toMatchSnapshot('import-export: warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(`import-export: ${file}`);
+        }
+      }
+    });
+  });
+
+  it('matches snapshot for `nameCache` option', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/import-export/entry.js`,
+      output: {
+        path: `${__dirname}/dist-import-export`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        nameCache: {},
+        mangle: false,
+        warnings: true,
+        output: {
+          beautify: true,
+        },
+      },
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('import-export: errors');
+      expect(warnings).toMatchSnapshot('import-export: warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(`import-export: ${file}`);
+        }
+      }
+    });
+  });
+
+  it('matches snapshot for `keep_classnames` option', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/import-export/entry.js`,
+      output: {
+        path: `${__dirname}/dist-import-export`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        keep_classnames: true,
+        mangle: false,
+        warnings: true,
+        output: {
+          beautify: true,
+        },
+      },
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('import-export: errors');
+      expect(warnings).toMatchSnapshot('import-export: warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(`import-export: ${file}`);
+        }
+      }
+    });
+  });
+
+  it('matches snapshot for `keep_fnames` option', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/import-export/entry.js`,
+      output: {
+        path: `${__dirname}/dist-import-export`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        keep_fnames: true,
+        mangle: false,
+        warnings: true,
+        output: {
+          beautify: true,
+        },
+      },
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('import-export: errors');
+      expect(warnings).toMatchSnapshot('import-export: warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(`import-export: ${file}`);
+        }
+      }
+    });
+  });
+
+  it('matches snapshot for `safari10` option', () => {
+    const compiler = createCompiler({
+      entry: `${__dirname}/fixtures/import-export/entry.js`,
+      output: {
+        path: `${__dirname}/dist-import-export`,
+        filename: '[name].js',
+        chunkFilename: '[id].[name].js',
+      },
+    });
+
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        safari10: true,
+        mangle: false,
+        warnings: true,
+        output: {
+          beautify: true,
+        },
+      },
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('import-export: errors');
+      expect(warnings).toMatchSnapshot('import-export: warnings');
+
+      for (const file in stats.compilation.assets) {
+        if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
+          expect(stats.compilation.assets[file].source()).toMatchSnapshot(`import-export: ${file}`);
+        }
+      }
+    });
+  });
+});