diff --git a/README.md b/README.md index 19042016..9b18f5f9 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ This plugin supports UglifyJS features as discussed below: | include | RegExp, Array | | Test only `include` files. | | exclude | RegExp, Array | | Files to `exclude` from testing. | | warningsFilter | function(source) -> boolean | | Allow to filter uglify warnings (since webpack 2.3.0) | +| parallel | boolean, object | false | Use multi-process parallel running and file cache to improve the build speed. |

Mangling

@@ -103,6 +104,14 @@ The `extractComments` option can be - `banner`: The banner text that points to the extracted file and will be added on top of the original file. will be added to the original file. Can be `false` (no banner), a `string`, or a `function (string) -> string` that will be called with the filename where extracted comments have been stored. Will be wrapped into comment. Default: `/*! For license information please see foo.js.LICENSE */` +

Run in parallel

+ +The `parallel` option can be + +- `true`: Enable multi-process parallel running with file cache +- an `object` consisting of the following keys, all optional: + - `workers`: The maximum number of concurrent runs. If it is `true`, it is equal to `require('os').cpus().length - 1`. + - `cache`: Enable file caching. If it is `true`, it is equal to `"node_modules/.cache/uglifyjs-webpack-plugin"`.

Maintainers

diff --git a/package-lock.json b/package-lock.json index b94aba53..b52bc539 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,9 @@ "dev": true }, "acorn": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", - "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", - "dev": true + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", + "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==" }, "acorn-dynamic-import": { "version": "2.0.2", @@ -47,27 +46,23 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, "dependencies": { "acorn": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" } } }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=" }, "ajv-keywords": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=" }, "align-text": { "version": "0.1.4", @@ -90,20 +85,17 @@ "ansi-escapes": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", - "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", - "dev": true + "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=" }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "anymatch": { "version": "1.3.0", @@ -123,11 +115,15 @@ "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", "dev": true }, + "aproba": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==" + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=" }, "arr-diff": { "version": "2.0.0", @@ -136,9 +132,9 @@ "dev": true }, "arr-flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz", - "integrity": "sha1-onTthawIhJtr14R8RYB0XcUa37E=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "array-equal": { @@ -162,14 +158,12 @@ "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=" }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.2.1", @@ -180,8 +174,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, "asn1": { "version": "0.2.3", @@ -246,8 +239,7 @@ "babel-code-frame": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", - "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", - "dev": true + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=" }, "babel-core": { "version": "6.25.0", @@ -556,9 +548,9 @@ "dev": true }, "babel-preset-env": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.5.2.tgz", - "integrity": "sha1-zUrpCm6Utwn5c3SzPl+LmDVWre8=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.0.tgz", + "integrity": "sha512-OVgtQRuOZKckrILgMA5rvctvFZPv72Gua9Rt006AiPoB0DJKGN07UmaQA+qRrYgK71MVct8fFhT0EyNWYorVew==", "dev": true }, "babel-preset-jest": { @@ -606,8 +598,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { "version": "1.2.1", @@ -634,6 +625,11 @@ "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=", "dev": true }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + }, "bn.js": { "version": "4.11.7", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz", @@ -663,8 +659,7 @@ "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=" }, "braces": { "version": "1.8.5", @@ -796,42 +791,37 @@ } } }, + "cacache": { + "version": "9.2.9", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.9.tgz", + "integrity": "sha512-ghg1j5OyTJ6qsrqU++dN23QiTDxb5AZCFGsF3oB+v9v/gY+F4X8L/0gdQMEjd+8Ot3D29M2etX5PKozHRn2JQw==" + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=" }, "callsites": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } + "dev": true }, "caniuse-lite": { - "version": "1.0.30000696", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000696.tgz", - "integrity": "sha1-MPJpXSoBoN/XeaJquD9NE0s9pcw=", + "version": "1.0.30000697", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000697.tgz", + "integrity": "sha1-El+wBgS2P7sYjblqZnziki3NbN0=", "dev": true }, "capture-stack-trace": { @@ -855,8 +845,7 @@ "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=" }, "chokidar": { "version": "1.7.0", @@ -864,6 +853,11 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, "ci-info": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", @@ -871,16 +865,15 @@ "dev": true }, "cipher-base": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.3.tgz", - "integrity": "sha1-7qvxlEGc6QDaMBjCB9IS8qbfCgc=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true }, "circular-json": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", - "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", - "dev": true + "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=" }, "cli-boxes": { "version": "1.0.0", @@ -891,8 +884,7 @@ "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=" }, "cli-spinners": { "version": "0.1.2", @@ -923,20 +915,26 @@ "cli-width": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", - "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", - "dev": true + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=" }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", @@ -963,11 +961,16 @@ "dev": true }, "commander": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.10.0.tgz", - "integrity": "sha512-q/r9trjmuikWDRJNTBHAVnWhuU6w+z80KgBq7j9YDclik5E7X4xi0KnlZBNFA1zOQ+SH/vHMWd2mC9QTOz7GpA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, "compare-func": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", @@ -985,14 +988,12 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=" }, "configstore": { "version": "3.1.0", @@ -1120,6 +1121,11 @@ "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", "dev": true }, + "copy-concurrently": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.3.tgz", + "integrity": "sha1-Rft4ZiSaHKiJqlcI5svSc+dbslA=" + }, "core-js": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", @@ -1129,8 +1135,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cosmiconfig": { "version": "1.1.0", @@ -1230,6 +1235,11 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -1277,8 +1287,7 @@ "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=" }, "decamelize": { "version": "1.2.0", @@ -1295,8 +1304,7 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "default-require-extensions": { "version": "1.0.0", @@ -1343,9 +1351,9 @@ "dev": true }, "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.0.tgz", + "integrity": "sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==", "dev": true }, "diffie-hellman": { @@ -1357,8 +1365,7 @@ "doctrine": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", - "dev": true + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=" }, "domain-browser": { "version": "1.1.7", @@ -1378,6 +1385,23 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=" + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=" + } + } + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -1386,9 +1410,9 @@ "optional": true }, "electron-to-chromium": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz", - "integrity": "sha1-ZK8Pnv08PGrNV9cfg7Scp+6cS0M=", + "version": "1.3.15", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz", + "integrity": "sha1-CDl5NIkcvPrrvRi4KpW1pIETg2k=", "dev": true }, "elegant-spinner": { @@ -1409,17 +1433,21 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=" + }, "enhanced-resolve": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz", - "integrity": "sha1-n0tib1dyRe3PSyrYPYbhf09CHew=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.3.0.tgz", + "integrity": "sha512-2qbxE7ek3YxPJ1ML6V+satHkzHpJQKWkRHmRx6mfAoW59yP8YH8BFplbegSP+u2hBd6B6KCOpvJQ3dZAP+hkpg==", "dev": true }, "errno": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", - "dev": true + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=" }, "error-ex": { "version": "1.3.1", @@ -1466,8 +1494,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "1.8.1", @@ -1505,8 +1532,7 @@ "eslint": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.1.1.tgz", - "integrity": "sha1-+svfz+Pg+s06i4DcmMTmwTrlgt8=", - "dev": true + "integrity": "sha1-+svfz+Pg+s06i4DcmMTmwTrlgt8=" }, "eslint-config-webpack": { "version": "1.2.5", @@ -1515,21 +1541,41 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", - "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz", + "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", "dev": true }, "eslint-module-utils": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", - "dev": true + "dev": true, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true + } + } }, "eslint-plugin-import": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.6.0.tgz", - "integrity": "sha512-JdkYDmMMjhxW6X/IVclD+vQXO6e2nJJT4cKcyTw95mvBCWkr8THXKFhc+WCvGvOscjGuLQzUB7tBeJddrg2jig==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz", + "integrity": "sha512-HGYmpU9f/zJaQiKNQOVfHUh2oLWW3STBrCgH0sHTX1xtsxYlH1zjLh8FlQGEIdZSdTbUMaV36WaZ6ImXkenGxQ==", "dev": true, "dependencies": { "doctrine": { @@ -1573,44 +1619,37 @@ "eslint-scope": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=" }, "espree": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", - "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", - "dev": true + "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=" }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, "esquery": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=" }, "esrecurse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=" }, "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "event-emitter": { "version": "0.3.5", @@ -1669,8 +1708,7 @@ "external-editor": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", - "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", - "dev": true + "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=" }, "extglob": { "version": "0.3.2", @@ -1685,16 +1723,15 @@ "dev": true }, "fast-deep-equal": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-0.1.0.tgz", - "integrity": "sha1-XG9FmaumszPuM0Li7ZeGcvEAH40=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fb-watchman": { "version": "2.0.0", @@ -1705,14 +1742,12 @@ "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=" }, "file-entry-cache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=" }, "filename-regex": { "version": "2.0.1", @@ -1732,32 +1767,38 @@ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", "dev": true }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=" + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" }, "flat-cache": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", - "dev": true, "dependencies": { "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=" }, "globby": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=" } } }, + "flush-write-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", + "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=" + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1782,6 +1823,11 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=" + }, "fs-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", @@ -1794,11 +1840,15 @@ "integrity": "sha1-jNF0XItPiinIyuw5JHaSG6GV9WA=", "dev": true }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.1.2", @@ -2466,14 +2516,12 @@ "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" }, "generate-object-property": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=" }, "get-caller-file": { "version": "1.0.2", @@ -2546,8 +2594,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==" }, "glob-base": { "version": "0.3.0", @@ -2564,8 +2611,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { "version": "6.1.0", @@ -2582,8 +2628,7 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { "version": "1.0.1", @@ -2608,11 +2653,41 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true, + "optional": true + } + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true } } }, @@ -2637,8 +2712,7 @@ "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" }, "has-flag": { "version": "1.0.0", @@ -2653,9 +2727,9 @@ "dev": true }, "hash.js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.2.tgz", - "integrity": "sha512-SsNl8Ro2uz5xUTRYq8ysWzX8B7jCj7pLvX3opktaI6ZrTT2YElqjFVJXHJZe+5Aby20c9UC7elCjJDe1dhTaAw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true }, "hawk": { @@ -2709,8 +2783,7 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", - "dev": true + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" }, "ieee754": { "version": "1.1.8", @@ -2718,11 +2791,15 @@ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, "ignore": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", - "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", - "dev": true + "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=" }, "import-lazy": { "version": "2.1.0", @@ -2733,8 +2810,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", @@ -2751,14 +2827,12 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.4", @@ -2769,8 +2843,7 @@ "inquirer": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.1.1.tgz", - "integrity": "sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ==", - "dev": true + "integrity": "sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ==" }, "interpret": { "version": "1.0.3", @@ -2853,8 +2926,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-glob": { "version": "2.0.1", @@ -2865,8 +2937,7 @@ "is-my-json-valid": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", - "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", - "dev": true + "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=" }, "is-npm": { "version": "1.0.0", @@ -2889,20 +2960,17 @@ "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" }, "is-path-in-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=" }, "is-path-inside": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "dev": true + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=" }, "is-posix-bracket": { "version": "0.1.1", @@ -2919,14 +2987,12 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" }, "is-redirect": { "version": "1.0.0", @@ -2937,8 +3003,7 @@ "is-resolvable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=" }, "is-retry-allowed": { "version": "1.1.0", @@ -2985,8 +3050,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -3074,41 +3138,11 @@ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true - }, "jest-cli": { "version": "20.0.4", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-20.0.4.tgz", "integrity": "sha1-5TKxnYiuW8bEF+iwWTpv6VSx3JM=", "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true } } }, @@ -3208,41 +3242,11 @@ "integrity": "sha1-osgCIZxCA/dU3xQE5JAYYWnRJNg=", "dev": true, "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true - }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true } } }, @@ -3267,14 +3271,12 @@ "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", - "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", - "dev": true + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", + "integrity": "sha512-0LoUNELX4S+iofCT8f4uEHIiRBR+c2AINyC8qRWfC6QNruLtxVZRJaPcu/xwMgFIgDxF25tGHaDjvxzJCNE9yw==" }, "jsbn": { "version": "0.1.1", @@ -3286,8 +3288,7 @@ "jschardet": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz", - "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=", - "dev": true + "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=" }, "jsdom": { "version": "9.12.0", @@ -3330,8 +3331,7 @@ "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=" }, "json-stringify-safe": { "version": "5.0.1", @@ -3348,8 +3348,7 @@ "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, "jsonparse": { "version": "1.3.1", @@ -3360,8 +3359,7 @@ "jsonpointer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" }, "JSONStream": { "version": "1.3.1", @@ -3416,13 +3414,12 @@ "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=" }, "lint-staged": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-4.0.0.tgz", - "integrity": "sha1-wVZp9ZhhSm5oCQMD4XWnmdSODYU=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-4.0.1.tgz", + "integrity": "sha1-BTZUaYmEOdut6KRViTzxHiTRKw8=", "dev": true, "dependencies": { "execa": { @@ -3538,14 +3535,12 @@ "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -3642,14 +3637,12 @@ "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==" }, "make-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", - "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", - "dev": true + "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=" }, "makeerror": { "version": "1.0.11", @@ -3722,8 +3715,7 @@ "mimic-fn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", - "dev": true + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" }, "minimalistic-assert": { "version": "1.0.0", @@ -3740,20 +3732,22 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mississippi": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz", + "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=" }, "modify-values": { "version": "1.0.0", @@ -3761,6 +3755,11 @@ "integrity": "sha1-4rbN65zhn5kxelNyLz2/XfXqqrI=", "dev": true }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=" + }, "mrm-core": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mrm-core/-/mrm-core-1.1.0.tgz", @@ -3778,14 +3777,12 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "nan": { "version": "2.6.2", @@ -3797,8 +3794,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "nested-error-stacks": { "version": "2.0.0", @@ -4155,8 +4151,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object.omit": { "version": "2.0.1", @@ -4167,35 +4162,32 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=" }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "dependencies": { "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true } } }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=" + }, "ora": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", @@ -4249,8 +4241,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "output-file-sync": { "version": "1.1.2", @@ -4267,14 +4258,12 @@ "p-limit": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=" }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" }, "p-map": { "version": "1.1.1", @@ -4294,6 +4283,11 @@ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=" + }, "parse-asn1": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", @@ -4333,20 +4327,17 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "1.0.0", @@ -4381,46 +4372,27 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=" }, "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true - } - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=" }, "pluralize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", - "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", - "dev": true + "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=" }, "pre-commit": { "version": "1.2.2", @@ -4431,8 +4403,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prepend-http": { "version": "1.0.4", @@ -4475,14 +4446,17 @@ "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "progress": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, "prop-ini": { "version": "0.0.2", @@ -4493,14 +4467,12 @@ "prr": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", - "dev": true + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=" }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "public-encrypt": { "version": "4.0.0", @@ -4508,6 +4480,16 @@ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", "dev": true }, + "pump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", + "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=" + }, + "pumpify": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", + "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=" + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -4613,10 +4595,9 @@ } }, "readable-stream": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz", - "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", - "dev": true + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==" }, "readdirp": { "version": "2.1.0", @@ -4749,8 +4730,7 @@ "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=" }, "resolve": { "version": "1.3.3", @@ -4761,14 +4741,12 @@ "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=" }, "right-align": { "version": "0.1.3", @@ -4779,8 +4757,7 @@ "rimraf": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=" }, "ripemd160": { "version": "2.0.1", @@ -4791,32 +4768,33 @@ "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=" + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=" }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" }, "rx-lite-aggregates": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=" }, "rxjs": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.1.tgz", - "integrity": "sha1-ti91fyeURdJloYpY+wpw3JDpFiY=", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.2.tgz", + "integrity": "sha1-KjI2/L8D31e64G/Wly/ZnlwI/Pc=", "dev": true }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "sane": { "version": "1.6.0", @@ -4907,8 +4885,7 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "slash": { "version": "1.0.0", @@ -4919,8 +4896,7 @@ "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" }, "slide": { "version": "1.1.6", @@ -4995,8 +4971,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.13.1", @@ -5012,6 +4987,11 @@ } } }, + "ssri": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-4.1.6.tgz", + "integrity": "sha512-WUbCdgSAMQjTFZRWvSPpauryvREEA+Krn19rx67UlJEJx/M192ZHxMmJXjZ4tkdFm+Sb0SXGlENeQVlA5wY7kA==" + }, "staged-git-files": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz", @@ -5148,12 +5128,22 @@ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true }, + "stream-each": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.0.tgz", + "integrity": "sha1-HpXUdXP1gNgU3A/4zQ9m8c5TyZE=" + }, "stream-http": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", "dev": true }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, "stream-to-observable": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz", @@ -5163,8 +5153,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==" }, "string-length": { "version": "1.0.1", @@ -5176,19 +5165,16 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz", "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", - "dev": true, "dependencies": { "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=" } } }, @@ -5201,8 +5187,7 @@ "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" }, "strip-bom": { "version": "2.0.0", @@ -5225,8 +5210,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "suffix": { "version": "0.1.0", @@ -5237,8 +5221,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "symbol-observable": { "version": "1.0.4", @@ -5255,8 +5238,7 @@ "table": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", - "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", - "dev": true + "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=" }, "tapable": { "version": "0.2.6", @@ -5285,8 +5267,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "throat": { "version": "3.2.0", @@ -5297,14 +5278,12 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" }, "timed-out": { "version": "4.0.1", @@ -5321,8 +5300,7 @@ "tmp": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "dev": true + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=" }, "tmpl": { "version": "1.0.4", @@ -5375,8 +5353,7 @@ "tryit": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=" }, "tty-browserify": { "version": "0.0.0", @@ -5400,14 +5377,12 @@ "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=" }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-es": { "version": "3.0.24", @@ -5421,12 +5396,6 @@ } } }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true - }, "uglify-to-browserify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", @@ -5438,7 +5407,37 @@ "version": "0.4.6", "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", - "dev": true + "dev": true, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true + } + } + }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=" + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=" }, "unique-string": { "version": "1.0.0", @@ -5501,8 +5500,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.1.0", @@ -5559,15 +5557,15 @@ "dev": true }, "webpack": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.0.0.tgz", - "integrity": "sha1-7pvOvyEkf3FTy0EBaMq0XjpZ1Nc=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.1.0.tgz", + "integrity": "sha512-BWF3vW30ZpqscTpIsqUi6gTnXdvoeS+uEcmoAjtg5Yq0xtxebjz8xjDl3AWV4P5Mi3RqS5Xhq+Q5vvcjU3iUAw==", "dev": true, "dependencies": { "ajv": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.0.tgz", - "integrity": "sha1-wXNQJMXaLvdcwZBxMHPUTwmL9IY=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.1.tgz", + "integrity": "sha1-3NAwRRdYg7obY25a6ew9+auFMjo=", "dev": true }, "ajv-keywords": { @@ -5621,9 +5619,9 @@ } }, "webpack-defaults": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/webpack-defaults/-/webpack-defaults-1.4.0.tgz", - "integrity": "sha512-kuLwz68ZqZw59TdUMoXIw+XRXUNOls8pluuPDlU4lDOBaHcGtjFxEdPESPq1s3slTnA0uk0YgQheVRb3MFnTVg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/webpack-defaults/-/webpack-defaults-1.5.0.tgz", + "integrity": "sha1-Xvg7w37CQVmf3eZX2dtnk8Z3lV8=", "dev": true }, "webpack-merge": { @@ -5704,16 +5702,14 @@ "dev": true }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "worker-farm": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.3.1.tgz", - "integrity": "sha1-QzMRK7SbF6oFC4eJXKayys9A5f8=", - "dev": true + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.4.1.tgz", + "integrity": "sha512-tgFAtgOYLPutkAyzgpS6VJFL5HY+0ui1Tvua+fITgz8ByaJTMFGtazR6xxQfwfiAcbwE+2fLG/K49wc2TfwCNw==" }, "wrap-ansi": { "version": "2.1.0", @@ -5738,14 +5734,12 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=" }, "write-file-atomic": { "version": "2.1.0", @@ -5768,26 +5762,49 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + } + } }, "yargs-parser": { "version": "5.0.0", diff --git a/package.json b/package.json index 69bc60c0..cd9b8115 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,12 @@ "webpack-defaults": "webpack-defaults" }, "dependencies": { + "cacache": "^9.2.9", + "find-cache-dir": "^1.0.0", "source-map": "^0.5.6", "uglify-es": "^3.0.24", - "webpack-sources": "^1.0.1" + "webpack-sources": "^1.0.1", + "worker-farm": "^1.4.1" }, "devDependencies": { "babel-cli": "^6.24.1", diff --git a/src/index.js b/src/index.js index 1730f2b9..c8573915 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,7 @@ import { SourceMapConsumer } from 'source-map'; import { SourceMapSource, RawSource, ConcatSource } from 'webpack-sources'; import RequestShortener from 'webpack/lib/RequestShortener'; import ModuleFilenameHelpers from 'webpack/lib/ModuleFilenameHelpers'; -import uglify from 'uglify-es'; +import Uglify from './uglify'; /* eslint-disable no-param-reassign @@ -15,15 +15,6 @@ import uglify from 'uglify-es'; const warningRegex = /\[.+:([0-9]+),([0-9]+)\]/; -const defaultUglifyOptions = { - output: { - comments: /^\**!|@preserve|@license|@cc_on/, - beautify: false, - semicolons: true, - shebang: true, - }, -}; - class UglifyJsPlugin { constructor(options) { if (typeof options !== 'object' || Array.isArray(options)) { @@ -34,23 +25,8 @@ class UglifyJsPlugin { this.options.test = this.options.test || /\.js($|\?)/i; this.options.warningsFilter = this.options.warningsFilter || (() => true); - - this.uglifyOptions = this.options.uglifyOptions || {}; - } - - static buildDefaultUglifyOptions({ ecma, warnings, parse = {}, compress = {}, mangle, output, toplevel, ie8 }) { - return { - ecma, - warnings, - parse, - compress, - mangle: mangle == null ? true : mangle, - // Ignoring sourcemap from options - sourceMap: null, - output: { ...defaultUglifyOptions.output, ...output }, - toplevel, - ie8, - }; + this.options.uglifyOptions = this.options.uglifyOptions || {}; + this.options.parallel = this.options.parallel || {}; } static buildError(err, file, sourceMap, requestShortener) { @@ -64,10 +40,10 @@ class UglifyJsPlugin { return new Error(`${file} from UglifyJs\n${err.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${err.line},${err.col}]`); } return new Error(`${file} from UglifyJs\n${err.message} [${file}:${err.line},${err.col}]`); - } else if (err.msg) { - return new Error(`${file} from UglifyJs\n${err.msg}`); + } else if (err.stack) { + return new Error(`${file} from UglifyJs\n${err.stack}`); } - return new Error(`${file} from UglifyJs\n${err.stack}`); + return new Error(`${file} from UglifyJs\n${err.message}`); } static buildWarnings(warnings, file, sourceMap, warningsFilter, requestShortener) { @@ -91,71 +67,9 @@ class UglifyJsPlugin { }, []); } - static buildCommentsFunction(options, uglifyOptions, extractedComments) { - const condition = {}; - const commentsOpts = uglifyOptions.output.comments; - if (typeof options.extractComments === 'string' || options.extractComments instanceof RegExp) { - // extractComments specifies the extract condition and commentsOpts specifies the preserve condition - condition.preserve = commentsOpts; - condition.extract = options.extractComments; - } else if (Object.prototype.hasOwnProperty.call(options.extractComments, 'condition')) { - // Extract condition is given in extractComments.condition - condition.preserve = commentsOpts; - condition.extract = options.extractComments.condition; - } else { - // No extract condition is given. Extract comments that match commentsOpts instead of preserving them - condition.preserve = false; - condition.extract = commentsOpts; - } - - // Ensure that both conditions are functions - ['preserve', 'extract'].forEach((key) => { - let regexStr; - let regex; - switch (typeof (condition[key])) { - case 'boolean': - condition[key] = condition[key] ? () => true : () => false; - break; - case 'function': - break; - case 'string': - if (condition[key] === 'all') { - condition[key] = () => true; - break; - } - if (condition[key] === 'some') { - condition[key] = (astNode, comment) => comment.type === 'comment2' && /@preserve|@license|@cc_on/i.test(comment.value); - break; - } - regexStr = condition[key]; - condition[key] = (astNode, comment) => new RegExp(regexStr).test(comment.value); - break; - default: - regex = condition[key]; - condition[key] = (astNode, comment) => (regex.test(comment.value)); - } - }); - - // Redefine the comments function to extract and preserve - // comments according to the two conditions - return (astNode, comment) => { - if (condition.extract(astNode, comment)) { - extractedComments.push( - comment.type === 'comment2' ? `/*${comment.value}*/` : `//${comment.value}`, - ); - } - return condition.preserve(astNode, comment); - }; - } - apply(compiler) { const requestShortener = new RequestShortener(compiler.context); - // Copy uglify options - const uglifyOptions = UglifyJsPlugin.buildDefaultUglifyOptions(this.uglifyOptions); - // Making sure output options exists if there is an extractComments options - if (this.options.extractComments) { - uglifyOptions.output = uglifyOptions.output || {}; - } + compiler.plugin('compilation', (compilation) => { if (this.options.sourceMap) { @@ -166,13 +80,13 @@ class UglifyJsPlugin { } compilation.plugin('optimize-chunk-assets', (chunks, callback) => { + const uglify = new Uglify(this.options.parallel); const uglifiedAssets = new WeakSet(); + const tasks = []; chunks.reduce((acc, chunk) => acc.concat(chunk.files || []), []) .concat(compilation.additionalChunkAssets || []) .filter(ModuleFilenameHelpers.matchObject.bind(null, this.options)) .forEach((file) => { - // Reseting sourcemap to null - uglifyOptions.sourceMap = null; let sourceMap; const asset = compilation.assets[file]; if (uglifiedAssets.has(asset)) { @@ -182,6 +96,7 @@ class UglifyJsPlugin { try { let input; let inputSourceMap; + const cacheKey = `${compiler.outputPath}/${file}`; if (this.options.sourceMap) { if (asset.sourceAndMap) { const sourceAndMap = asset.sourceAndMap(); @@ -192,89 +107,104 @@ class UglifyJsPlugin { input = asset.source(); } sourceMap = new SourceMapConsumer(inputSourceMap); - // Add source map data - uglifyOptions.sourceMap = { - content: inputSourceMap, - }; } else { input = asset.source(); } // Handling comment extraction - const extractedComments = []; let commentsFile = false; if (this.options.extractComments) { - uglifyOptions.output.comments = UglifyJsPlugin.buildCommentsFunction(this.options, uglifyOptions, extractedComments); - commentsFile = this.options.extractComments.filename || `${file}.LICENSE`; if (typeof commentsFile === 'function') { commentsFile = commentsFile(file); } } - // Calling uglify - const { error, map, code, warnings } = uglify.minify({ [file]: input }, uglifyOptions); + tasks.push({ + cacheKey, + file, + input, + sourceMap, + inputSourceMap, + commentsFile, + extractComments: this.options.extractComments, + uglifyOptions: this.options.uglifyOptions, + }); + } catch (error) { + compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, compilation, requestShortener)); + } + }); - // Handling results - // Error case: add errors, and go to next file - if (error) { - compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, compilation, requestShortener)); - return; - } + uglify.runTasks(tasks, (tasksError, results) => { + if (tasksError) { + compilation.errors.push(tasksError); + return; + } - let outputSource; - if (map) { - outputSource = new SourceMapSource(code, file, JSON.parse(map), input, inputSourceMap); - } else { - outputSource = new RawSource(code); - } + results.forEach((data, index) => { + const { file, input, sourceMap, inputSourceMap, commentsFile } = tasks[index]; + const { error, map, code, warnings, extractedComments } = data; + + // Handling results + // Error case: add errors, and go to next file + if (error) { + compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, compilation, requestShortener)); + return; + } + + let outputSource; + if (map) { + outputSource = new SourceMapSource(code, file, JSON.parse(map), input, inputSourceMap); + } else { + outputSource = new RawSource(code); + } - // Write extracted comments to commentsFile - if (commentsFile && extractedComments.length > 0) { - // Add a banner to the original file - if (this.options.extractComments.banner !== false) { - let banner = this.options.extractComments.banner || `For license information please see ${commentsFile}`; - if (typeof banner === 'function') { - banner = banner(commentsFile); - } - if (banner) { - outputSource = new ConcatSource( - `/*! ${banner} */\n`, outputSource, - ); - } + // Write extracted comments to commentsFile + if (commentsFile && extractedComments.length > 0) { + // Add a banner to the original file + if (this.options.extractComments.banner !== false) { + let banner = this.options.extractComments.banner || `For license information please see ${commentsFile}`; + if (typeof banner === 'function') { + banner = banner(commentsFile); + } + if (banner) { + outputSource = new ConcatSource( + `/*! ${banner} */\n`, outputSource, + ); } + } - const commentsSource = new RawSource(`${extractedComments.join('\n\n')}\n`); - if (commentsFile in compilation.assets) { - // commentsFile already exists, append new comments... - if (compilation.assets[commentsFile] instanceof ConcatSource) { - compilation.assets[commentsFile].add('\n'); - compilation.assets[commentsFile].add(commentsSource); - } else { - compilation.assets[commentsFile] = new ConcatSource( - compilation.assets[commentsFile], '\n', commentsSource, - ); - } + const commentsSource = new RawSource(`${extractedComments.join('\n\n')}\n`); + if (commentsFile in compilation.assets) { + // commentsFile already exists, append new comments... + if (compilation.assets[commentsFile] instanceof ConcatSource) { + compilation.assets[commentsFile].add('\n'); + compilation.assets[commentsFile].add(commentsSource); } else { - compilation.assets[commentsFile] = commentsSource; + compilation.assets[commentsFile] = new ConcatSource( + compilation.assets[commentsFile], '\n', commentsSource, + ); } + } else { + compilation.assets[commentsFile] = commentsSource; } + } - // Updating assets - uglifiedAssets.add(compilation.assets[file] = outputSource); + // Updating assets + uglifiedAssets.add(compilation.assets[file] = outputSource); - // Handling warnings - if (warnings) { - const warnArr = UglifyJsPlugin.buildWarnings(warnings, file, sourceMap, this.options.warningsFilter, requestShortener); - if (warnArr.length > 0) { - compilation.warnings.push(new Error(`${file} from UglifyJs\n${warnArr.join('\n')}`)); - } + // Handling warnings + if (warnings) { + const warnArr = UglifyJsPlugin.buildWarnings(warnings, file, sourceMap, this.options.warningsFilter, requestShortener); + if (warnArr.length > 0) { + compilation.warnings.push(new Error(`${file} from UglifyJs\n${warnArr.join('\n')}`)); } - } catch (error) { - compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, compilation, requestShortener)); } }); - callback(); + + uglify.exit(); + callback(); + }); }); }); } diff --git a/src/uglify/cache.js b/src/uglify/cache.js new file mode 100644 index 00000000..8c5f36e8 --- /dev/null +++ b/src/uglify/cache.js @@ -0,0 +1,20 @@ +import crypto from 'crypto'; +import cacache from 'cacache'; + +const sha512 = 'sha512'; +const getHash = data => `${sha512}-${ + crypto.createHash(sha512).update(data).digest('base64') +}`; + +export const get = (cacheDirectory, key, identifier) => cacache.get(cacheDirectory, key).then(({ data, metadata }) => { + const hash = getHash(identifier); + if (metadata.hash !== hash) { + return Promise.reject(new Error('The cache has expired')); + } + return JSON.parse(data); +}); + +export const put = (cacheDirectory, key, data, identifier) => { + const hash = getHash(identifier); + return cacache.put(cacheDirectory, key, JSON.stringify(data), { metadata: { hash } }); +}; diff --git a/src/uglify/index.js b/src/uglify/index.js new file mode 100644 index 00000000..0f596517 --- /dev/null +++ b/src/uglify/index.js @@ -0,0 +1,90 @@ +import os from 'os'; +import findCacheDir from 'find-cache-dir'; +import workerFarm from 'worker-farm'; +import minify from './minify'; +import { get, put } from './cache'; +import { encode } from './serialization'; +import versions from './versions'; + +let workerFile = require.resolve('./worker'); + +try { + // run test + workerFile = require.resolve('../../dist/uglify/worker'); +} catch (e) { } // eslint-disable-line no-empty + +export default class { + constructor(parallel = {}) { + let options = parallel; + if (typeof parallel === 'boolean') { + options = { cache: parallel, workers: parallel }; + } + const { cache, workers } = options; + this.cache = cache === true ? findCacheDir({ name: 'uglifyjs-webpack-plugin' }) : cache; + this.workers = workers === true ? os.cpus().length - 1 : Math.min(Number(workers) || 0, os.cpus().length - 1); + } + + worker(options, callback) { + if (this.workers > 0) { + this.workerFarm = workerFarm({ + maxConcurrentWorkers: this.workers, + }, workerFile); + this.worker = (opt, cb) => this.workerFarm(JSON.stringify(opt, encode), cb); + } else { + this.worker = (opt, cb) => { + try { + const result = minify(opt); + cb(null, result); + } catch (errors) { + cb(errors); + } + }; + } + + this.worker(options, callback); + } + + exit() { + if (this.workerFarm) { + workerFarm.end(this.workerFarm); + } + } + + runTasks(tasks, callback) { + if (!tasks.length) { + callback(null, []); + return; + } + + let toRun = tasks.length; + const results = []; + const step = (index, data) => { + toRun -= 1; + results[index] = data; + if (!toRun) { + callback(null, results); + } + }; + + tasks.forEach((task, index) => { + const cacheIdentifier = `${versions.uglify}|${versions.plugin}|${task.input}`; + const enqueue = () => { + this.worker(task, (error, data) => { + const result = error ? { error } : data; + const done = () => step(index, result); + if (this.cache && !result.error) { + put(this.cache, task.cacheKey, data, cacheIdentifier).then(done, done); + } else { + done(); + } + }); + }; + if (this.cache) { + get(this.cache, task.cacheKey, cacheIdentifier).then(data => step(index, data), enqueue); + } else { + enqueue(); + } + }); + } +} + diff --git a/src/uglify/minify.js b/src/uglify/minify.js new file mode 100644 index 00000000..3ea0930d --- /dev/null +++ b/src/uglify/minify.js @@ -0,0 +1,102 @@ +import uglify from 'uglify-es'; + +const buildDefaultUglifyOptions = ({ ecma, warnings, parse = {}, compress = {}, mangle, output, toplevel, ie8 }) => { + return { + ecma, + warnings, + parse, + compress, + mangle: mangle == null ? true : mangle, + // Ignoring sourcemap from options + sourceMap: null, + output: { + comments: /^\**!|@preserve|@license|@cc_on/, + beautify: false, + semicolons: true, + shebang: true, + ...output, + }, + toplevel, + ie8, + }; +}; + +const buildComments = (options, uglifyOptions, extractedComments) => { + const condition = {}; + const commentsOpts = uglifyOptions.output.comments; + if (typeof options.extractComments === 'string' || options.extractComments instanceof RegExp) { + // extractComments specifies the extract condition and commentsOpts specifies the preserve condition + condition.preserve = commentsOpts; + condition.extract = options.extractComments; + } else if (Object.prototype.hasOwnProperty.call(options.extractComments, 'condition')) { + // Extract condition is given in extractComments.condition + condition.preserve = commentsOpts; + condition.extract = options.extractComments.condition; + } else { + // No extract condition is given. Extract comments that match commentsOpts instead of preserving them + condition.preserve = false; + condition.extract = commentsOpts; + } + + // Ensure that both conditions are functions + ['preserve', 'extract'].forEach((key) => { + let regexStr; + let regex; + switch (typeof (condition[key])) { + case 'boolean': + condition[key] = condition[key] ? () => true : () => false; + break; + case 'function': + break; + case 'string': + if (condition[key] === 'all') { + condition[key] = () => true; + break; + } + if (condition[key] === 'some') { + condition[key] = (astNode, comment) => comment.type === 'comment2' && /@preserve|@license|@cc_on/i.test(comment.value); + break; + } + regexStr = condition[key]; + condition[key] = (astNode, comment) => new RegExp(regexStr).test(comment.value); + break; + default: + regex = condition[key]; + condition[key] = (astNode, comment) => (regex.test(comment.value)); + } + }); + + // Redefine the comments function to extract and preserve + // comments according to the two conditions + return (astNode, comment) => { + if (condition.extract(astNode, comment)) { + extractedComments.push( + comment.type === 'comment2' ? `/*${comment.value}*/` : `//${comment.value}`, + ); + } + return condition.preserve(astNode, comment); + }; +}; + +const minify = (options) => { + const { file, input, inputSourceMap, extractComments } = options; + // Copy uglify options + const uglifyOptions = buildDefaultUglifyOptions(options.uglifyOptions || {}); + + // Add source map data + if (inputSourceMap) { + uglifyOptions.sourceMap = { + content: inputSourceMap, + }; + } + + const extractedComments = []; + if (extractComments) { + uglifyOptions.output.comments = buildComments(options, uglifyOptions, extractedComments); + } + + const { error, map, code, warnings } = uglify.minify({ [file]: input }, uglifyOptions); + return { error, map, code, warnings, extractedComments }; +}; + +export default minify; diff --git a/src/uglify/serialization.js b/src/uglify/serialization.js new file mode 100644 index 00000000..7ac19574 --- /dev/null +++ b/src/uglify/serialization.js @@ -0,0 +1,34 @@ +/* eslint-disable no-new-func */ +const toType = value => (Object.prototype.toString.call(value).slice(8, -1)); + +export const encode = (key, value) => { + const type = toType(value); + if (encode[type]) { + return `<${type}>${encode[type](value, key)}`; + } + return value; +}; + +encode.RegExp = value => String(value); +encode.Function = value => String(value); + +export const decode = (key, value) => { + if (typeof value === 'string') { + const regex = /^<([A-Z]\w+)>([\w\W]*)$/; + const match = value.match(regex); + if (match && decode[match[1]]) { + return decode[match[1]](match[2], key); + } + } + + return value; +}; + +decode.RegExp = value => (Function(`return ${value}`)()); +decode.Function = (value, key) => Function(` + try { + return ${value}.apply(null, arguments); + } catch(err) { + throw new Error('the option "${key}" performs an error in the child process: ' + err.message); + } +`); diff --git a/src/uglify/versions.js b/src/uglify/versions.js new file mode 100644 index 00000000..d398e951 --- /dev/null +++ b/src/uglify/versions.js @@ -0,0 +1,5 @@ +export default { + uglify: require('uglify-es/package.json').version, // eslint-disable-line global-require + plugin: require('../../package.json').version, // eslint-disable-line global-require +}; + diff --git a/src/uglify/worker.js b/src/uglify/worker.js new file mode 100644 index 00000000..924d544a --- /dev/null +++ b/src/uglify/worker.js @@ -0,0 +1,10 @@ +import minify from './minify'; +import { decode } from './serialization'; + +module.exports = (options, callback) => { + try { + callback(null, minify(JSON.parse(options, decode))); + } catch (errors) { + callback(errors); + } +}; diff --git a/test/__snapshots__/parallel-options.test.js.snap b/test/__snapshots__/parallel-options.test.js.snap new file mode 100644 index 00000000..868100bb --- /dev/null +++ b/test/__snapshots__/parallel-options.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`errors 1`] = `Array []`; + +exports[`main.0c220ec66316af2c1b24.js 1`] = `"webpackJsonp([0],[function(o,n){o.exports=function(){console.log(7)}}],[0]);"`; + +exports[`manifest.6afe1bc6685e9ab36c1c.js 1`] = `"!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,l=0,s=[];l { }); }); + it('extracts license information to separate file', () => { + compilationEventBinding.handler([{ + files: ['test4.js'], + }], () => { + expect(compilation.errors.length).toBe(0); + /* eslint-disable no-underscore-dangle */ + expect(compilation.assets['test4.license.js'].source()).toContain('/*! this comment should be extracted */'); + expect(compilation.assets['test4.license.js'].source()).toContain('// another comment that should be extracted to a separate file'); + expect(compilation.assets['test4.license.js'].source()).not.toEqual(expect.stringContaining('/* this will not be extracted */')); + /* eslint-enable no-underscore-dangle */ + }); + }); + describe('with warningsFilter set', () => { describe('and the filter returns true', () => { beforeEach(() => { @@ -374,19 +387,6 @@ describe('when applied with all options', () => { }); }); }); - - it('extracts license information to separate file', () => { - compilationEventBinding.handler([{ - files: ['test4.js'], - }], () => { - expect(compilation.errors.length).toBe(0); - /* eslint-disable no-underscore-dangle */ - expect(compilation.assets['test4.license.js']._value).toEqual(expect.stringContaining('/*! this comment should be extracted */')); - expect(compilation.assets['test4.license.js']._value).toEqual(expect.stringContaining('// another comment that should be extracted to a separate file')); - expect(compilation.assets['test4.license.js']._value).not.toEqual(expect.stringContaining('/* this will not be extracted */')); - /* eslint-enable no-underscore-dangle */ - }); - }); }); }); }); diff --git a/test/empty-options.test.js b/test/empty-options.test.js index 44f7e363..605e45b3 100644 --- a/test/empty-options.test.js +++ b/test/empty-options.test.js @@ -95,8 +95,10 @@ describe('when applied with no options', () => { it('only calls callback once', () => { callback = jest.fn(); - compilationEventBinding.handler([''], callback); - expect(callback.mock.calls.length).toBe(1); + compilationEventBinding.handler([''], () => { + callback(); + expect(callback.mock.calls.length).toBe(1); + }); }); it('default only parses filenames ending with .js', () => { @@ -121,7 +123,7 @@ describe('when applied with no options', () => { }], () => { expect(compilation.errors.length).toBe(1); expect(compilation.errors[0]).toBeInstanceOf(Error); - expect(compilation.errors[0].message).toEqual(expect.stringContaining('TypeError')); + expect(compilation.errors[0].message).toEqual(expect.stringContaining('asset.source is not a function')); }); }); diff --git a/test/extract-comments-options.test.js b/test/extract-comments-options.test.js index 54d6386c..e050bfd0 100644 --- a/test/extract-comments-options.test.js +++ b/test/extract-comments-options.test.js @@ -71,7 +71,7 @@ describe('when options.extractComments', () => { }); }); - describe('normalizes when options.extractComments is regex', () => { + it('normalizes when options.extractComments is regex', () => { const pluginEnvironment = new PluginEnvironment(); const compilerEnv = pluginEnvironment.getEnvironmentStub(); compilerEnv.context = ''; @@ -105,7 +105,7 @@ describe('when options.extractComments', () => { }); }); - describe('converts boolean options.extractComments.condition to function', () => { + it('converts boolean options.extractComments.condition to function', () => { const pluginEnvironment = new PluginEnvironment(); const compilerEnv = pluginEnvironment.getEnvironmentStub(); compilerEnv.context = ''; diff --git a/test/parallel-options.test.js b/test/parallel-options.test.js new file mode 100644 index 00000000..8f29bed8 --- /dev/null +++ b/test/parallel-options.test.js @@ -0,0 +1,204 @@ +import cacache from 'cacache'; +import findCacheDir from 'find-cache-dir'; +import { RawSource } from 'webpack-sources'; +import UglifyJsPlugin from '../src/index'; +import { + PluginEnvironment, + createCompiler, + compile, + cleanErrorStack, +} from './helpers'; + +const cachePath = findCacheDir({ name: 'uglifyjs-webpack-plugin' }); + +cacache.rm.all(cachePath); + +describe('when options.parallel', () => { + let eventBindings; + let eventBinding; + + beforeEach(() => { + const pluginEnvironment = new PluginEnvironment(); + const compilerEnv = pluginEnvironment.getEnvironmentStub(); + compilerEnv.context = ''; + + const plugin = new UglifyJsPlugin({ + parallel: true, + }); + plugin.apply(compilerEnv); + eventBindings = pluginEnvironment.getEventBindings(); + }); + + it('binds one event handler', () => { + expect(eventBindings.length).toBe(1); + }); + + describe('compilation handler', () => { + beforeEach(() => { + [eventBinding] = eventBindings; + }); + + it('binds to compilation event', () => { + expect(eventBinding.name).toBe('compilation'); + }); + + describe('when called', () => { + let chunkPluginEnvironment; + let compilationEventBindings; + let compilationEventBinding; + let compilation; + let callback; + + beforeEach(() => { + chunkPluginEnvironment = new PluginEnvironment(); + compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { + 'test.js': {}, + 'test1.js': '', + 'test2.js': { + source: () => 'invalid javascript', + }, + 'test3.js': { + source: () => '/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }', + }, + }; + compilation.errors = []; + + eventBinding.handler(compilation); + compilationEventBindings = chunkPluginEnvironment.getEventBindings(); + }); + + it('binds one event handler', () => { + expect(compilationEventBindings.length).toBe(1); + }); + + describe('optimize-chunk-assets handler', () => { + beforeEach(() => { + [compilationEventBinding] = compilationEventBindings; + }); + + it('binds to optimize-chunk-assets event', () => { + expect(compilationEventBinding.name).toEqual('optimize-chunk-assets'); + }); + + it('only calls callback once', (done) => { + callback = jest.fn(); + compilationEventBinding.handler([''], () => { + callback(); + expect(callback.mock.calls.length).toBe(1); + done(); + }); + }); + + it('default only parses filenames ending with .js', (done) => { + compilationEventBinding.handler([{ + files: ['test', 'test.js'], + }], () => { + expect(Object.keys(compilation.assets).length).toBe(4); + done(); + }); + }); + + it('early returns if private property is already set', (done) => { + compilationEventBinding.handler([{ + files: ['test.js'], + }], () => { + expect(compilation.assets['test.js']).toEqual({}); + done(); + }); + }); + + it('outputs stack trace errors for invalid asset', (done) => { + compilationEventBinding.handler([{ + files: ['test1.js'], + }], () => { + expect(compilation.errors.length).toBe(1); + expect(compilation.errors[0]).toBeInstanceOf(Error); + expect(compilation.errors[0].message).toEqual(expect.stringContaining('asset.source is not a function')); + done(); + }); + }); + + it('outputs parsing errors for invalid javascript', (done) => { + compilationEventBinding.handler([{ + files: ['test2.js'], + }], () => { + expect(compilation.errors.length).toBe(1); + expect(compilation.errors[0]).toBeInstanceOf(Error); + expect(compilation.errors[0].message).toEqual(expect.stringContaining('Unexpected token')); + expect(compilation.errors[0].message).toEqual(expect.stringContaining('[test2.js:1,8]')); + done(); + }); + }); + + it('outputs no errors for valid javascript', (done) => { + compilationEventBinding.handler([{ + files: ['test3.js'], + }], () => { + expect(compilation.errors.length).toBe(0); + done(); + }); + }); + + it('outputs RawSource for valid javascript', (done) => { + compilationEventBinding.handler([{ + files: ['test3.js'], + }], () => { + expect(compilation.assets['test3.js']).toBeInstanceOf(RawSource); + done(); + }); + }); + + it('outputs mangled javascript', (done) => { + compilationEventBinding.handler([{ + files: ['test3.js'], + }], () => { + // eslint-disable-next-line no-underscore-dangle + expect(compilation.assets['test3.js']._value) + .not.toEqual(expect.stringContaining('longVariableName')); + done(); + }); + }); + + it('compresses and does not output beautified javascript', (done) => { + compilationEventBinding.handler([{ + files: ['test3.js'], + }], () => { + // eslint-disable-next-line no-underscore-dangle + expect(compilation.assets['test3.js']._value).not.toEqual(expect.stringContaining('\n')); + done(); + }); + }); + + it('preserves comments', (done) => { + compilationEventBinding.handler([{ + files: ['test3.js'], + }], () => { + // eslint-disable-next-line no-underscore-dangle + expect(compilation.assets['test3.js']._value).toEqual(expect.stringContaining('/**')); + done(); + }); + }); + }); + }); + }); + + it('matches snapshot', () => { + const compiler = createCompiler(); + new UglifyJsPlugin({ parallel: 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('errors'); + expect(warnings).toMatchSnapshot('warnings'); + + for (const file in stats.compilation.assets) { + if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) { + expect(stats.compilation.assets[file].source()).toMatchSnapshot(file); + } + } + }); + }); +}); diff --git a/test/uglify/__snapshots__/worker.test.js.snap b/test/uglify/__snapshots__/worker.test.js.snap new file mode 100644 index 00000000..6f064f11 --- /dev/null +++ b/test/uglify/__snapshots__/worker.test.js.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test1.js 1`] = ` +Object { + "code": "var foo=1;", + "error": undefined, + "extractedComments": Array [], + "map": undefined, + "warnings": undefined, +} +`; + +exports[`test2.js 1`] = ` +Object { + "code": "var foo=1;", + "error": undefined, + "extractedComments": Array [], + "map": undefined, + "warnings": undefined, +} +`; + +exports[`test3.js 1`] = ` +Object { + "code": "var foo=1;", + "error": undefined, + "extractedComments": Array [], + "map": undefined, + "warnings": undefined, +} +`; + +exports[`test4.js 1`] = ` +Object { + "code": "var foo=1;", + "error": undefined, + "extractedComments": Array [], + "map": undefined, + "warnings": undefined, +} +`; + +exports[`test5.js 1`] = ` +Object { + "code": "/******/function hello(o){console.log(o)}", + "error": undefined, + "extractedComments": Array [], + "map": undefined, + "warnings": undefined, +} +`; + +exports[`test6.js 1`] = ` +Object { + "code": "function foo(f){if(f)return bar()}", + "error": undefined, + "extractedComments": Array [], + "map": "{\\"version\\":3,\\"sources\\":[\\"test1.js\\"],\\"names\\":[\\"foo\\",\\"x\\",\\"not_called1\\"],\\"mappings\\":\\"AAAA,SAASA,IAAIC,GACT,GACIA,EAAA,OACAC\\"}", + "warnings": undefined, +} +`; diff --git a/test/uglify/cache.test.js b/test/uglify/cache.test.js new file mode 100644 index 00000000..f0242040 --- /dev/null +++ b/test/uglify/cache.test.js @@ -0,0 +1,30 @@ +import crypto from 'crypto'; +import findCacheDir from 'find-cache-dir'; +import { get, put } from '../../src/uglify/cache'; + +const hashAlgorithm = 'sha512'; +const getHash = data => `${hashAlgorithm}-${ + crypto.createHash(hashAlgorithm).update(data).digest('base64') +}`; + +const cacheDirectory = findCacheDir({ + name: 'uglify-webpack-plugin-test', +}); + +const data = { + file: 'test/content.js', + input: '"hello uglifyjs"', +}; + +describe('when cache', () => { + beforeEach(() => put(cacheDirectory, data.file, data.input, getHash(data.input))); + it('get cache', () => get(cacheDirectory, data.file, getHash(data.input)).then((input) => { + expect(data.input).toEqual(input); + })); + it('the cache has expired', () => { + data.input = 'hello world'; + return get(cacheDirectory, data.file, getHash(data.input)).then(() => Promise.reject(new Error('cache verification failed')), (error) => { + expect(error.message).toEqual('The cache has expired'); + }); + }); +}); diff --git a/test/uglify/serialization.test.js b/test/uglify/serialization.test.js new file mode 100644 index 00000000..032a11de --- /dev/null +++ b/test/uglify/serialization.test.js @@ -0,0 +1,35 @@ +import { encode, decode } from '../../src/uglify/serialization'; + +describe('serialization data', () => { + it('serialization function', () => { + const input = { + func: (a, b) => a + b, + }; + const string = JSON.stringify(input, encode); + const json = JSON.parse(string, decode); + expect(json.func).not.toBe(input.func); + expect(typeof json.func).toBe('function'); + expect(json.func(1, 2)).toBe(input.func(1, 2)); + }); + + it('serialization regexp', () => { + const input = { + regexp: /\s+/, + }; + const string = JSON.stringify(input, encode); + const json = JSON.parse(string, decode); + expect(json.regexp).not.toBe(input.regexp); + expect(json.regexp instanceof RegExp).toBe(true); + expect(json.regexp.toString()).toBe(input.regexp.toString()); + }); + + it('function operation failure should report critical information.', () => { + const a = 0; + const b = 1; + const input = { + func: () => a + b, + }; + const string = JSON.stringify(input, encode); + expect(() => (JSON.parse(string, decode)).func()).toThrow('the option "func" performs an error in the child process:'); + }); +}); diff --git a/test/uglify/worker.test.js b/test/uglify/worker.test.js new file mode 100644 index 00000000..1bd807e6 --- /dev/null +++ b/test/uglify/worker.test.js @@ -0,0 +1,124 @@ +import worker from '../../src/uglify/worker'; +import { encode } from '../../src/uglify/serialization'; + +describe('matches snapshot', () => { + it('normalizes when options.extractComments is regex', () => { + const options = { + file: 'test1.js', + input: 'var foo = 1;/* hello */', + uglifyOptions: { + output: { + comments: false, + }, + }, + extractComments: /foo/, + }; + worker(JSON.stringify(options, encode), (error, data) => { + if (error) { + throw error; + } + expect(data).toMatchSnapshot(options.file); + }); + }); + + it('normalizes when uglifyOptions.output.comments is string: all', () => { + const options = { + file: 'test2.js', + input: 'var foo = 1;/* hello */', + uglifyOptions: { + output: { + comments: 'all', + }, + }, + }; + worker(JSON.stringify(options, encode), (error, data) => { + if (error) { + throw error; + } + expect(data).toMatchSnapshot(options.file); + }); + }); + + it('normalizes when uglifyOptions.output.comments is string: some', () => { + const options = { + file: 'test3.js', + input: 'var foo = 1;/* hello */', + uglifyOptions: { + output: { + comments: 'some', + }, + }, + }; + worker(JSON.stringify(options, encode), (error, data) => { + if (error) { + throw error; + } + expect(data).toMatchSnapshot(options.file); + }); + }); + + it('normalizes when uglifyOptions.extractComments is number', () => { + const options = { + file: 'test4.js', + input: 'var foo = 1;/* hello */', + uglifyOptions: { + output: { + comments: 'some', + }, + }, + extractComments: 1, + }; + worker(JSON.stringify(options, encode), (error, data) => { + if (error) { + throw error; + } + expect(data).toMatchSnapshot(options.file); + }); + }); + + it('when applied with extract option set to a single file', () => { + const options = { + file: 'test5.js', + input: '/******/ function hello(a) {console.log(a)}', + uglifyOptions: { + output: { + comments: 'all', + }, + }, + extractComments: { + condition: 'should be extracted', + filename(file) { + return file.replace(/(\.\w+)$/, '.license$1'); + }, + banner(licenseFile) { + return `License information can be found in ${licenseFile}`; + }, + }, + }; + worker(JSON.stringify(options, encode), (error, data) => { + if (error) { + throw error; + } + expect(data).toMatchSnapshot(options.file); + }); + }); + + it('when options.inputSourceMap', () => { + const options = { + file: 'test6.js', + input: 'function foo(x) { if (x) { return bar(); not_called1(); } }', + inputSourceMap: { + version: 3, + sources: ['test1.js'], + names: ['foo', 'x', 'bar', 'not_called1'], + mappings: 'AAAA,QAASA,KAAIC,GACT,GAAIA,EAAG,CACH,MAAOC,MACPC', + }, + }; + worker(JSON.stringify(options, encode), (error, data) => { + if (error) { + throw error; + } + expect(data).toMatchSnapshot(options.file); + }); + }); +});