From 8dd3307c0892594ea8edacc6049186eb98374cc3 Mon Sep 17 00:00:00 2001 From: shellscape Date: Thu, 11 Jan 2018 11:15:26 -0500 Subject: [PATCH 001/162] ensures the HMRPlugin assigns module.hot before NodeStuffPlugin --- lib/HotModuleReplacementPlugin.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index f0eb9eac9..bdc35c4de 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -191,9 +191,12 @@ module.exports = class HotModuleReplacementPlugin { params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { parser.plugin("expression __webpack_hash__", ParserHelpers.toConstantDependency("__webpack_require__.h()")); parser.plugin("evaluate typeof __webpack_hash__", ParserHelpers.evaluateToString("string")); - parser.plugin("evaluate Identifier module.hot", function(expr) { - return ParserHelpers.evaluateToIdentifier("module.hot", !!this.state.compilation.hotUpdateChunkTemplate)(expr); - }); + parser.hooks.evaluateIdentifier.for("module.hot").tap({ + name: "HotModuleReplacementPlugin", + before: "NodeStuffPlugin" + }, expr => { + return ParserHelpers.evaluateToIdentifier("module.hot", !!parser.state.compilation.hotUpdateChunkTemplate)(expr); + }); parser.plugin("call module.hot.accept", function(expr) { if(!this.state.compilation.hotUpdateChunkTemplate) return false; if(expr.arguments.length >= 1) { From 490a32cfea2ab88dd0d46b1dcd2d09cf4ee49f43 Mon Sep 17 00:00:00 2001 From: Florent Cailhol Date: Wed, 7 Feb 2018 10:39:06 +0100 Subject: [PATCH 002/162] Update parser to support EcmaScript 2018 --- lib/Parser.js | 8 ++++++-- test/Parser.unittest.js | 22 +++++++++++++++++++--- yarn.lock | 6 +++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 09f6844c5..5bda48f2e 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -24,7 +24,7 @@ const joinRanges = (startRange, endRange) => { const defaultParserOptions = { ranges: true, locations: true, - ecmaVersion: 2017, + ecmaVersion: 2018, sourceType: "module", onComment: null, plugins: { @@ -1297,6 +1297,10 @@ class Parser extends Tapable { walkObjectExpression(expression) { for(let propIndex = 0, len = expression.properties.length; propIndex < len; propIndex++) { const prop = expression.properties[propIndex]; + if(prop.type === "SpreadElement") { + this.walkExpression(prop.argument); + continue; + } if(prop.computed) this.walkExpression(prop.key); if(prop.shorthand) @@ -1856,7 +1860,7 @@ class Parser extends Tapable { } static parse(code, options) { - const type = options.sourceType; + const type = options ? options.sourceType : "module"; const parserOptions = Object.assign(Object.create(null), defaultParserOptions, options); if(type === "auto") { diff --git a/test/Parser.unittest.js b/test/Parser.unittest.js index 34bab80b1..15d3a1225 100644 --- a/test/Parser.unittest.js +++ b/test/Parser.unittest.js @@ -468,13 +468,13 @@ describe("Parser", () => { const cases = { "async function": "async function x() {}", "async arrow function": "async () => {}", - "await expression": "async function x(y) { await y }" + "await expression": "async function x(y) { await y }", + "await iteration": "async function f() { for await (x of xs); }" }; - const parser = new Parser(); Object.keys(cases).forEach((name) => { const expr = cases[name]; it(name, () => { - const actual = parser.parse(expr); + const actual = Parser.parse(expr); should.strictEqual(typeof actual, "object"); }); }); @@ -511,4 +511,20 @@ describe("Parser", () => { }); }); }); + + describe("object rest/spread support", () => { + describe("should accept", () => { + const cases = { + "object spread": "({...obj})", + "object rest": "({...obj} = foo)" + }; + Object.keys(cases).forEach((name) => { + const expr = cases[name]; + it(name, () => { + const actual = Parser.parse(expr); + should.strictEqual(typeof actual, "object"); + }); + }); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 555ea00d5..081b2aea2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -47,7 +47,11 @@ acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.0.0, acorn@^5.2.1: +acorn@^5.0.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" + +acorn@^5.2.1: version "5.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" From 39438c7fe828e04575d0ead2a7be1687411fd382 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sat, 24 Feb 2018 13:12:26 +0100 Subject: [PATCH 003/162] unittest now also walks the ast --- test/Parser.unittest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Parser.unittest.js b/test/Parser.unittest.js index 15d3a1225..329017834 100644 --- a/test/Parser.unittest.js +++ b/test/Parser.unittest.js @@ -471,10 +471,11 @@ describe("Parser", () => { "await expression": "async function x(y) { await y }", "await iteration": "async function f() { for await (x of xs); }" }; + const parser = new Parser(); Object.keys(cases).forEach((name) => { const expr = cases[name]; it(name, () => { - const actual = Parser.parse(expr); + const actual = parser.parse(expr); should.strictEqual(typeof actual, "object"); }); }); From b0949cb2d26193bc4d384852927f00e51db1a824 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sat, 24 Feb 2018 13:12:38 +0100 Subject: [PATCH 004/162] add integration test for spread operator --- test/cases/parsing/spread/a.js | 1 + test/cases/parsing/spread/index.js | 11 +++++++++++ test/cases/parsing/spread/module.js | 6 ++++++ test/cases/parsing/spread/test.filter.js | 5 +++++ test/helpers/supportsSpread.js | 9 +++++++++ 5 files changed, 32 insertions(+) create mode 100644 test/cases/parsing/spread/a.js create mode 100644 test/cases/parsing/spread/index.js create mode 100644 test/cases/parsing/spread/module.js create mode 100644 test/cases/parsing/spread/test.filter.js create mode 100644 test/helpers/supportsSpread.js diff --git a/test/cases/parsing/spread/a.js b/test/cases/parsing/spread/a.js new file mode 100644 index 000000000..f74a2f2b5 --- /dev/null +++ b/test/cases/parsing/spread/a.js @@ -0,0 +1 @@ +module.exports = "ok"; diff --git a/test/cases/parsing/spread/index.js b/test/cases/parsing/spread/index.js new file mode 100644 index 000000000..924a2c7e7 --- /dev/null +++ b/test/cases/parsing/spread/index.js @@ -0,0 +1,11 @@ +import X, { A, B } from "./module"; +import * as M from "./module"; + +it("should support spread operator", function() { + var o1 = { ...X }; + o1.should.be.eql({ A: "A", B: "B" }); + var o2 = { ...({ X }) }; + o2.should.be.eql({ X: { A: "A", B: "B" } }); + var o3 = { ...M }; + o3.should.be.eql({ default: { A: "A", B: "B" }, A: "A", B: "B" }); +}); diff --git a/test/cases/parsing/spread/module.js b/test/cases/parsing/spread/module.js new file mode 100644 index 000000000..7a590ef8e --- /dev/null +++ b/test/cases/parsing/spread/module.js @@ -0,0 +1,6 @@ +const A = "A"; +const B = "B"; + +export default { A, B }; + +export { A, B }; diff --git a/test/cases/parsing/spread/test.filter.js b/test/cases/parsing/spread/test.filter.js new file mode 100644 index 000000000..741b76b8c --- /dev/null +++ b/test/cases/parsing/spread/test.filter.js @@ -0,0 +1,5 @@ +var supportsSpread = require("../../../helpers/supportsSpread"); + +module.exports = function(config) { + return supportsSpread(); +}; diff --git a/test/helpers/supportsSpread.js b/test/helpers/supportsSpread.js new file mode 100644 index 000000000..3ea317b61 --- /dev/null +++ b/test/helpers/supportsSpread.js @@ -0,0 +1,9 @@ +module.exports = function supportsSpread() { + try { + var x = { a: true }, y; // eslint-disable-line no-unused-vars + eval("y = { ...x }"); + return y !== x && y.a; + } catch(e) { + return false; + } +}; From 6bf5df53a304512d845cfffa78799416f3c92012 Mon Sep 17 00:00:00 2001 From: Naveen Jain Date: Wed, 21 Feb 2018 19:51:05 +0530 Subject: [PATCH 005/162] Fixed template.md --- examples/multiple-entry-points/README.md | 14 +++++++------- examples/multiple-entry-points/template.md | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/multiple-entry-points/README.md b/examples/multiple-entry-points/README.md index ff024dbfb..78770d452 100644 --- a/examples/multiple-entry-points/README.md +++ b/examples/multiple-entry-points/README.md @@ -4,15 +4,15 @@ In this example you have two (HTML) pages `pageA` and `pageB`. You want to creat You can see how to define multiple entry points via the `entry` option. -You can use +You can use You can see the output files: * `commons.js` contains: - * the module system - * chunk loading logic * module `common.js` which is used in both pages * `pageA.js` contains: (`pageB.js` is similar) + * the module system + * chunk loading logic * the entry point `pageA.js` * it would contain any other module that is only used by `pageA` * `0.chunk.js` is an additional chunk which is used by both pages. It contains: @@ -572,7 +572,7 @@ module.exports = function(msg) { ``` Hash: 0a1b2c3d4e5f6a7b8c9d -Version: webpack 4.0.0-beta.2 +Version: webpack 4.0.0-beta.1 Asset Size Chunks Chunk Names 0.js 363 bytes 0 [emitted] commons.js 267 bytes 1 [emitted] commons @@ -588,8 +588,8 @@ chunk {0} 0.js 91 bytes <{1}> <{2}> <{3}> [rendered] cjs require ./shared [2] ./pageB.js 3:14-33 amd require ./shared [3] ./pageA.js 2:0-4:2 chunk {1} commons.js (commons) 26 bytes ={2}= ={3}= >{0}< [initial] [rendered] split chunk (cache group: commons) (name: commons) - > ./pageA pageA > ./pageB pageB + > ./pageA pageA [1] ./common.js 26 bytes {1} [built] cjs require ./common [0] ./shared.js 1:13-32 cjs require ./common [2] ./pageB.js 1:13-32 @@ -608,7 +608,7 @@ chunk {3} pageA.js (pageA) 108 bytes ={1}= >{0}< [entry] [rendered] ``` Hash: 0a1b2c3d4e5f6a7b8c9d -Version: webpack 4.0.0-beta.2 +Version: webpack 4.0.0-beta.1 Asset Size Chunks Chunk Names 0.js 120 bytes 0 [emitted] commons.js 95 bytes 1 [emitted] commons @@ -624,8 +624,8 @@ chunk {0} 0.js 91 bytes <{1}> <{2}> <{3}> [rendered] cjs require ./shared [2] ./pageB.js 3:14-33 amd require ./shared [3] ./pageA.js 2:0-4:2 chunk {1} commons.js (commons) 26 bytes ={2}= ={3}= >{0}< [initial] [rendered] split chunk (cache group: commons) (name: commons) - > ./pageA pageA > ./pageB pageB + > ./pageA pageA [1] ./common.js 26 bytes {1} [built] cjs require ./common [0] ./shared.js 1:13-32 cjs require ./common [2] ./pageB.js 1:13-32 diff --git a/examples/multiple-entry-points/template.md b/examples/multiple-entry-points/template.md index 5a6074a96..4b0ea594b 100644 --- a/examples/multiple-entry-points/template.md +++ b/examples/multiple-entry-points/template.md @@ -4,15 +4,15 @@ In this example you have two (HTML) pages `pageA` and `pageB`. You want to creat You can see how to define multiple entry points via the `entry` option. -You can use +You can use You can see the output files: * `commons.js` contains: - * the module system - * chunk loading logic * module `common.js` which is used in both pages * `pageA.js` contains: (`pageB.js` is similar) + * the module system + * chunk loading logic * the entry point `pageA.js` * it would contain any other module that is only used by `pageA` * `0.chunk.js` is an additional chunk which is used by both pages. It contains: From e52f323750d3780980ef154bdec1ec0362b315e1 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sat, 24 Feb 2018 14:31:18 +0100 Subject: [PATCH 006/162] optimize performance of assignDepth --- lib/Compilation.js | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/Compilation.js b/lib/Compilation.js index 6fcbf42e0..c3e34ba70 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -1007,45 +1007,44 @@ class Compilation extends Tapable { } assignDepth(module) { - const assignDepthToModule = (module, depth) => { - // enter module - if(typeof module.depth === "number" && module.depth <= depth) return; - module.depth = depth; + const queue = new Set([module]); + let depth; - // enter it as block - assignDepthToDependencyBlock(module, depth + 1); + module.depth = 0; + + const enqueueJob = module => { + const d = module.depth; + if(typeof d === "number" && d <= depth) return; + queue.add(module); + module.depth = depth; }; const assignDepthToDependency = (dependency, depth) => { if(dependency.module) { - queue.push(() => assignDepthToModule(dependency.module, depth)); + enqueueJob(dependency.module); } }; - const assignDepthToDependencyBlock = (block, depth) => { - const iteratorDependency = d => assignDepthToDependency(d, depth); - - const iteratorBlock = b => assignDepthToDependencyBlock(b, depth); - + const assignDepthToDependencyBlock = block => { if(block.variables) { - iterationBlockVariable(block.variables, iteratorDependency); + iterationBlockVariable(block.variables, assignDepthToDependency); } if(block.dependencies) { - iterationOfArrayCallback(block.dependencies, iteratorDependency); + iterationOfArrayCallback(block.dependencies, assignDepthToDependency); } if(block.blocks) { - iterationOfArrayCallback(block.blocks, iteratorBlock); + iterationOfArrayCallback(block.blocks, assignDepthToDependencyBlock); } }; - const queue = [() => { - assignDepthToModule(module, 0); - }]; + for(module of queue) { + queue.delete(module); + depth = module.depth; - while(queue.length) { - queue.pop()(); + depth++; + assignDepthToDependencyBlock(module); } } From 4c25bfbaf2e01cf23708a381319b43367701e5b5 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sat, 24 Feb 2018 15:55:43 +0100 Subject: [PATCH 007/162] 4.0.0-beta.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e9898030..ced0fbaf2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "4.0.0-beta.2", + "version": "4.0.0-beta.3", "author": "Tobias Koppers @sokra", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "license": "MIT", From 518d1e092cf17a943cdb34b0551f7cf412e9a9a7 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 15 Nov 2017 13:52:01 +0100 Subject: [PATCH 008/162] replace js-beautify with prettier --- .editorconfig | 4 +++ .eslintrc.js | 31 +++------------- .prettierrc | 4 +++ package.json | 10 +++--- yarn.lock | 98 ++++++++++++++------------------------------------- 5 files changed, 45 insertions(+), 102 deletions(-) create mode 100644 .prettierrc diff --git a/.editorconfig b/.editorconfig index 012966bd9..7228de405 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,6 +12,10 @@ max_line_length = 233 indent_style = space indent_size = 2 +[.prettierrc] +indent_style = space +indent_size = 2 + [*.yml] indent_style = space indent_size = 2 diff --git a/.eslintrc.js b/.eslintrc.js index dece7c39f..12149e7f6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,9 @@ module.exports = { "root": true, - "plugins": ["node"], + "plugins": [ + "prettier", + "node" + ], "extends": ["eslint:recommended", "plugin:node/recommended"], "env": { "node": true, @@ -9,7 +12,7 @@ module.exports = { }, "parserOptions": { "ecmaVersion": 2017 }, "rules": { - "quotes": ["error", "double"], + "prettier/prettier": "error", "no-undef": "error", "no-extra-semi": "error", "semi": "error", @@ -21,36 +24,12 @@ module.exports = { "brace-style": "error", "eol-last": "error", "no-extra-bind": "warn", - "no-empty": "off", - "no-multiple-empty-lines": "error", - "no-multi-spaces": "error", "no-process-exit": "warn", - "space-in-parens": "error", - "no-trailing-spaces": "error", "no-use-before-define": "off", "no-unused-vars": ["error", { "args": "none" }], - "key-spacing": "error", - "space-infix-ops": "error", "no-unsafe-negation": "error", "no-loop-func": "warn", - "space-before-function-paren": ["error", "never"], - "space-before-blocks": "error", - "object-curly-spacing": ["error", "always"], "indent": "off", - "keyword-spacing": ["error", { - "after": false, - "overrides": { - "const": { "after": true }, - "try": { "after": true }, - "else": { "after": true }, - "throw": { "after": true }, - "case": { "after": true }, - "return": { "after": true }, - "finally": { "after": true }, - "do": { "after": true }, - "of": { "after": true } - } - }], "no-console": "off", "valid-jsdoc": "error", "node/no-unsupported-features": "error", diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..d2702b8a1 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 2, + "useTabs": true +} diff --git a/package.json b/package.json index ced0fbaf2..09ed831a5 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "webpack-sources": "^1.0.1" }, "devDependencies": { - "beautify-lint": "^1.0.3", "benchmark": "^2.1.1", "bundle-loader": "~0.5.0", "codacy-coverage": "^2.0.1", @@ -37,6 +36,7 @@ "es6-promise-polyfill": "^1.1.1", "eslint": "^4.3.0", "eslint-plugin-node": "^5.1.1", + "eslint-plugin-prettier": "^2.3.1", "express": "~4.13.1", "file-loader": "^1.1.6", "glob": "^7.1.2", @@ -44,13 +44,13 @@ "istanbul": "^0.4.5", "jade": "^1.11.0", "jade-loader": "~0.8.0", - "js-beautify": "^1.5.10", "json-loader": "^0.5.7", "less": "^2.5.1", "less-loader": "^4.0.3", "lodash": "^4.17.4", "mocha": "^3.2.0", "mocha-lcov-reporter": "^1.0.0", + "prettier": "^1.8.2", "raw-loader": "~0.5.0", "react": "^15.2.1", "react-dom": "^15.2.1", @@ -101,10 +101,10 @@ "circleci:lint": "npm run lint-files", "build:examples": "cd examples && node buildAll.js", "pretest": "npm run lint-files", - "lint-files": "npm run lint && npm run beautify-lint && npm run schema-lint", + "lint-files": "npm run lint && npm run schema-lint", "lint": "eslint lib bin hot buildin \"test/*.js\" \"test/**/webpack.config.js\" \"examples/**/webpack.config.js\"", "fix": "npm run lint -- --fix", - "beautify-lint": "beautify-lint \"lib/**/*.js\" \"hot/**/*.js\" \"bin/**/*.js\" \"benchmark/*.js\" \"test/*.js\" \"test/**/webpack.config.js\" \"examples/**/webpack.config.js\"", + "pretty-files": "prettier \"lib/**.*\" \"bin/**.*\" \"hot/**.*\" \"buildin/**.*\" \"test/*.js\" \"test/**/webpack.config.js\" \"examples/**/webpack.config.js\" --write", "schema-lint": "mocha test/*.lint.js --opts test/lint-mocha.opts", "benchmark": "mocha --max-old-space-size=4096 --harmony --trace-deprecation test/*.benchmark.js -R spec", "cover": "npm run cover:init && npm run cover:all && npm run cover:report", @@ -114,6 +114,6 @@ "cover:unit": "node --max-old-space-size=4096 --harmony --trace-deprecation ./node_modules/istanbul/lib/cli.js cover --report none node_modules/mocha/bin/_mocha -- test/*.unittest.js", "cover:report": "istanbul report", "cover:report-min": "istanbul report --report lcovonly", - "publish-patch": "npm run lint && npm run beautify-lint && mocha && npm version patch && git push && git push --tags && npm publish" + "publish-patch": "npm run lint && mocha && npm version patch && git push && git push --tags && npm publish" } } diff --git a/yarn.lock b/yarn.lock index f1048374a..745dc02aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -244,7 +244,7 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" -async@1.x, async@^1.4.0, async@^1.5.0: +async@1.x, async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -323,15 +323,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -beautify-lint@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/beautify-lint/-/beautify-lint-1.0.4.tgz#954b10f0bcd0a93dd17d0ed519b8996b701247db" - dependencies: - async "^1.5.0" - diff "^2.2.1" - glob "^6.0.1" - js-beautify "^1.5.10" - benchmark@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" @@ -357,7 +348,7 @@ bluebird@^2.3, bluebird@^2.9.x: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" -bluebird@^3.0.5, bluebird@^3.5.0: +bluebird@^3.5.0: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -811,13 +802,6 @@ concat-stream@^1.5.0, concat-stream@^1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -config-chain@~1.1.5: - version "1.1.11" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" @@ -1176,10 +1160,6 @@ diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" -diff@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99" - diff@^3.1.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" @@ -1217,16 +1197,6 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -editorconfig@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" - dependencies: - bluebird "^3.0.5" - commander "^2.9.0" - lru-cache "^3.2.0" - semver "^5.1.0" - sigmund "^1.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1315,6 +1285,13 @@ eslint-plugin-node@^5.1.1: resolve "^1.3.3" semver "5.3.0" +eslint-plugin-prettier@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.3.1.tgz#e7a746c67e716f335274b88295a9ead9f544e44d" + dependencies: + fast-diff "^1.1.1" + jest-docblock "^21.0.0" + eslint-scope@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" @@ -1533,6 +1510,10 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" +fast-diff@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -1812,16 +1793,6 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -2102,9 +2073,9 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -ini@^1.3.4, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" +ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" inquirer@^3.0.6: version "3.3.0" @@ -2399,6 +2370,10 @@ jade@^1.11.0: void-elements "~2.0.1" with "~4.0.0" +jest-docblock@^21.0.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + joi@^6.4.x: version "6.10.1" resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" @@ -2412,15 +2387,6 @@ js-base64@^2.1.9: version "2.4.0" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" -js-beautify@^1.5.10: - version "1.7.5" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.7.5.tgz#69d9651ef60dbb649f65527b53674950138a7919" - dependencies: - config-chain "~1.1.5" - editorconfig "^0.13.2" - mkdirp "~0.5.0" - nopt "~3.0.1" - js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -2687,12 +2653,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: dependencies: js-tokens "^3.0.0" -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - dependencies: - pseudomap "^1.0.1" - lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -3005,7 +2965,7 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" -nopt@3.x, nopt@~3.0.1: +nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: @@ -3547,6 +3507,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8" + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -3589,10 +3553,6 @@ prop-types@^15.5.10: loose-envify "^1.3.1" object-assign "^4.1.1" -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - proxy-addr@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.0.10.tgz#0d40a82f801fc355567d2ecb65efe3f077f121c5" @@ -3604,7 +3564,7 @@ prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" -pseudomap@^1.0.1, pseudomap@^1.0.2: +pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -4024,7 +3984,7 @@ semver@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -semver@^5.1.0, semver@^5.3.0: +semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -4165,10 +4125,6 @@ should@^11.1.1: should-type-adaptors "^1.0.1" should-util "^1.0.0" -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" From 5238159d211576bb313d99d487e415f3799af795 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sun, 25 Feb 2018 02:00:20 +0100 Subject: [PATCH 009/162] run prettier on existing code --- bin/webpack.js | 8 +- buildin/global.js | 7 +- buildin/harmony-module.js | 6 +- buildin/module.js | 4 +- examples/coffee-script/webpack.config.js | 10 +- .../0-vendor/webpack.config.js | 8 +- .../1-app/webpack.config.js | 8 +- .../explicit-vendor-chunk/webpack.config.js | 2 - examples/externals/webpack.config.js | 2 +- examples/hybrid-routing/webpack.config.js | 2 +- examples/i18n/webpack.config.js | 10 +- examples/loader/webpack.config.js | 10 +- examples/multi-compiler/webpack.config.js | 2 - examples/source-map/webpack.config.js | 6 +- examples/wasm-simple/webpack.config.js | 10 +- hot/.eslintrc | 1 - hot/dev-server.js | 62 +- hot/log-apply-result.js | 18 +- hot/log.js | 13 +- hot/only-dev-server.js | 116 +- hot/poll.js | 43 +- hot/signal.js | 70 +- lib/APIPlugin.js | 58 +- lib/AmdMainTemplatePlugin.js | 50 +- lib/AsyncDependenciesBlock.js | 12 +- lib/AsyncDependencyToInitialChunkError.js | 4 +- lib/AutomaticPrefetchPlugin.js | 39 +- lib/BannerPlugin.js | 50 +- lib/BasicEvaluatedExpression.js | 37 +- lib/CachePlugin.js | 90 +- lib/CaseSensitiveModulesWarning.js | 24 +- lib/Chunk.js | 157 +- lib/ChunkGroup.js | 78 +- lib/ChunkTemplate.js | 16 +- lib/CompatibilityPlugin.js | 74 +- lib/Compilation.js | 1116 ++++++++------- lib/Compiler.js | 301 ++-- lib/ConstPlugin.js | 280 ++-- lib/ContextExclusionPlugin.js | 4 +- lib/ContextModule.js | 292 ++-- lib/ContextModuleFactory.js | 279 ++-- lib/ContextReplacementPlugin.js | 82 +- lib/DefinePlugin.js | 246 ++-- lib/DelegatedModule.js | 18 +- lib/DelegatedModuleFactoryPlugin.js | 84 +- lib/DelegatedPlugin.js | 23 +- lib/DependenciesBlock.js | 54 +- lib/DependenciesBlockVariable.js | 15 +- lib/Dependency.js | 4 +- lib/DllEntryPlugin.js | 39 +- lib/DllModuleFactory.js | 10 +- lib/DllPlugin.js | 8 +- lib/DllReferencePlugin.js | 61 +- lib/DynamicEntryPlugin.js | 69 +- lib/EntryOptionPlugin.js | 10 +- lib/Entrypoint.js | 4 +- lib/EnvironmentPlugin.js | 29 +- lib/ErrorHelpers.js | 21 +- lib/EvalDevToolModulePlugin.js | 2 +- lib/EvalDevToolModuleTemplatePlugin.js | 49 +- ...valSourceMapDevToolModuleTemplatePlugin.js | 134 +- lib/EvalSourceMapDevToolPlugin.js | 24 +- lib/ExportPropertyMainTemplatePlugin.js | 12 +- lib/ExtendedAPIPlugin.js | 82 +- lib/ExternalModule.js | 62 +- lib/ExternalModuleFactoryPlugin.js | 154 +- lib/ExternalsPlugin.js | 8 +- lib/FlagDependencyExportsPlugin.js | 209 +-- lib/FlagDependencyUsagePlugin.js | 137 +- lib/FlagInitialModulesAsUsedPlugin.js | 32 +- lib/FunctionModulePlugin.js | 6 +- lib/FunctionModuleTemplatePlugin.js | 123 +- lib/GraphHelpers.js | 8 +- lib/HashedModuleIdsPlugin.js | 49 +- lib/HotModuleReplacement.runtime.js | 324 +++-- lib/HotModuleReplacementPlugin.js | 593 +++++--- lib/HotUpdateChunkTemplate.js | 54 +- lib/IgnorePlugin.js | 16 +- lib/JavascriptGenerator.js | 105 +- lib/JavascriptModulesPlugin.js | 196 ++- lib/JsonGenerator.js | 23 +- lib/JsonModulesPlugin.js | 25 +- lib/JsonParser.js | 2 +- lib/LibManifestPlugin.js | 101 +- lib/LibraryTemplatePlugin.js | 77 +- lib/LoaderOptionsPlugin.js | 39 +- lib/LoaderTargetPlugin.js | 11 +- lib/MainTemplate.js | 280 +++- lib/Module.js | 83 +- lib/ModuleBuildError.js | 10 +- lib/ModuleDependencyError.js | 5 +- lib/ModuleDependencyWarning.js | 5 +- lib/ModuleError.js | 8 +- lib/ModuleFilenameHelpers.js | 61 +- lib/ModuleParseError.js | 18 +- lib/ModuleReason.js | 19 +- lib/ModuleTemplate.js | 61 +- lib/ModuleWarning.js | 10 +- lib/MultiCompiler.js | 202 +-- lib/MultiEntryPlugin.js | 55 +- lib/MultiModule.js | 20 +- lib/MultiModuleFactory.js | 5 +- lib/MultiStats.js | 58 +- lib/MultiWatching.js | 20 +- lib/NamedChunksPlugin.js | 9 +- lib/NamedModulesPlugin.js | 8 +- lib/NoEmitOnErrorsPlugin.js | 10 +- lib/NoModeWarning.js | 3 +- lib/NodeStuffPlugin.js | 226 ++- lib/NormalModule.js | 238 ++-- lib/NormalModuleFactory.js | 488 ++++--- lib/NormalModuleReplacementPlugin.js | 50 +- lib/OptionsDefaulter.js | 56 +- lib/Parser.js | 1264 ++++++++++------- lib/ParserHelpers.js | 22 +- lib/PrefetchPlugin.js | 24 +- lib/ProgressPlugin.js | 53 +- lib/ProvidePlugin.js | 100 +- lib/RawModule.js | 6 +- lib/RecordIdsPlugin.js | 198 ++- lib/RequestShortener.js | 33 +- lib/RequireJsStuffPlugin.js | 71 +- lib/ResolverFactory.js | 28 +- lib/RuleSet.js | 322 +++-- lib/RuntimeTemplate.js | 272 ++-- lib/SetVarMainTemplatePlugin.js | 31 +- lib/SingleEntryPlugin.js | 31 +- lib/SizeFormatHelpers.js | 6 +- lib/SourceMapDevToolModuleOptionsPlugin.js | 44 +- lib/SourceMapDevToolPlugin.js | 371 +++-- lib/Stats.js | 850 ++++++----- lib/Template.js | 123 +- lib/TemplatedPathPlugin.js | 110 +- lib/UmdMainTemplatePlugin.js | 277 ++-- lib/UseStrictPlugin.js | 57 +- lib/WarnCaseSensitiveModulesPlugin.js | 39 +- lib/WarnNoModeSetPlugin.js | 2 +- lib/WatchIgnorePlugin.js | 56 +- lib/Watching.js | 94 +- lib/WebAssemblyModulesPlugin.js | 81 +- lib/WebAssemblyParser.js | 28 +- lib/WebpackOptionsApply.js | 189 ++- lib/WebpackOptionsDefaulter.js | 157 +- lib/WebpackOptionsValidationError.js | 284 ++-- lib/compareLocations.js | 30 +- lib/debug/ProfilingPlugin.js | 234 +-- lib/dependencies/AMDDefineDependency.js | 46 +- .../AMDDefineDependencyParserPlugin.js | 365 ++--- lib/dependencies/AMDPlugin.js | 269 +++- lib/dependencies/AMDRequireArrayDependency.js | 6 +- .../AMDRequireDependenciesBlock.js | 18 +- ...AMDRequireDependenciesBlockParserPlugin.js | 217 +-- lib/dependencies/AMDRequireDependency.js | 110 +- lib/dependencies/CommonJsPlugin.js | 171 ++- .../CommonJsRequireContextDependency.js | 1 - .../CommonJsRequireDependencyParserPlugin.js | 127 +- lib/dependencies/ConstDependency.js | 2 +- lib/dependencies/ContextDependency.js | 32 +- lib/dependencies/ContextDependencyHelpers.js | 128 +- .../ContextDependencyTemplateAsId.js | 23 +- .../ContextDependencyTemplateAsRequireCall.js | 17 +- lib/dependencies/ContextElementDependency.js | 2 +- lib/dependencies/HarmonyAcceptDependency.js | 11 +- .../HarmonyCompatibilityDependency.js | 2 +- .../HarmonyDetectionParserPlugin.js | 40 +- .../HarmonyExportDependencyParserPlugin.js | 170 ++- .../HarmonyExportExpressionDependency.js | 8 +- .../HarmonyExportHeaderDependency.js | 4 +- ...armonyExportImportedSpecifierDependency.js | 362 +++-- .../HarmonyExportSpecifierDependency.js | 8 +- lib/dependencies/HarmonyImportDependency.js | 31 +- .../HarmonyImportDependencyParserPlugin.js | 271 ++-- .../HarmonyImportSideEffectDependency.js | 4 +- .../HarmonyImportSpecifierDependency.js | 71 +- lib/dependencies/HarmonyInitDependency.js | 23 +- lib/dependencies/HarmonyModulesPlugin.js | 136 +- .../HarmonyTopLevelThisParserPlugin.js | 23 +- lib/dependencies/ImportContextDependency.js | 1 - lib/dependencies/ImportParserPlugin.js | 153 +- lib/dependencies/ImportPlugin.js | 75 +- lib/dependencies/LoaderPlugin.js | 117 +- lib/dependencies/LocalModuleDependency.js | 8 +- lib/dependencies/LocalModulesHelpers.js | 19 +- .../ModuleDependencyTemplateAsId.js | 3 +- .../ModuleDependencyTemplateAsRequireId.js | 3 +- .../RequireContextDependencyParserPlugin.js | 51 +- lib/dependencies/RequireContextPlugin.js | 176 ++- .../RequireEnsureDependenciesBlock.js | 17 +- ...uireEnsureDependenciesBlockParserPlugin.js | 91 +- lib/dependencies/RequireEnsureDependency.js | 30 +- lib/dependencies/RequireEnsurePlugin.js | 68 +- lib/dependencies/RequireHeaderDependency.js | 2 +- lib/dependencies/RequireIncludeDependency.js | 8 +- .../RequireIncludeDependencyParserPlugin.js | 20 +- lib/dependencies/RequireIncludePlugin.js | 57 +- .../RequireResolveContextDependency.js | 1 - .../RequireResolveDependencyParserPlugin.js | 43 +- .../RequireResolveHeaderDependency.js | 2 +- lib/dependencies/SystemPlugin.js | 128 +- lib/dependencies/UnsupportedDependency.js | 6 +- .../WebAssemblyImportDependency.js | 2 +- lib/dependencies/WebpackMissingModule.js | 14 +- lib/dependencies/getFunctionExpression.js | 17 +- lib/formatLocation.js | 37 +- lib/node/NodeChunkTemplatePlugin.js | 20 +- lib/node/NodeEnvironmentPlugin.js | 14 +- lib/node/NodeHotUpdateChunkTemplatePlugin.js | 37 +- lib/node/NodeMainTemplate.runtime.js | 11 +- lib/node/NodeMainTemplateAsync.runtime.js | 26 +- lib/node/NodeMainTemplatePlugin.js | 395 +++--- lib/node/NodeSourcePlugin.js | 158 ++- lib/node/NodeTargetPlugin.js | 3 +- lib/node/NodeTemplatePlugin.js | 10 +- lib/node/NodeWatchFileSystem.js | 47 +- .../ReadFileCompileWasmMainTemplatePlugin.js | 160 ++- lib/node/ReadFileCompileWasmTemplatePlugin.js | 15 +- lib/optimize/AggressiveMergingPlugin.js | 119 +- lib/optimize/AggressiveSplittingPlugin.js | 443 +++--- lib/optimize/ChunkModuleIdRangePlugin.js | 31 +- lib/optimize/ConcatenatedModule.js | 1088 +++++++++----- lib/optimize/EnsureChunkConditionsPlugin.js | 92 +- lib/optimize/FlagIncludedChunksPlugin.js | 37 +- lib/optimize/LimitChunkCountPlugin.js | 78 +- lib/optimize/MergeDuplicateChunksPlugin.js | 105 +- lib/optimize/MinChunkSizePlugin.js | 91 +- lib/optimize/ModuleConcatenationPlugin.js | 510 ++++--- lib/optimize/OccurrenceOrderPlugin.js | 189 +-- lib/optimize/RemoveEmptyChunksPlugin.js | 22 +- lib/optimize/RemoveParentModulesPlugin.js | 74 +- lib/optimize/RuntimeChunkPlugin.js | 15 +- lib/optimize/SideEffectsFlagPlugin.js | 178 +-- lib/optimize/SplitChunksPlugin.js | 561 ++++---- lib/performance/AssetsOverSizeLimitWarning.js | 11 +- .../EntrypointsOverSizeLimitWarning.js | 19 +- lib/performance/NoAsyncChunksWarning.js | 3 +- lib/performance/SizeLimitsPlugin.js | 46 +- lib/prepareOptions.js | 11 +- lib/util/Queue.js | 2 +- lib/util/Semaphore.js | 4 +- lib/util/SetHelpers.js | 22 +- lib/util/SortableSet.js | 18 +- lib/util/StackedSetMap.js | 48 +- lib/util/cachedMerge.js | 8 +- lib/util/createHash.js | 26 +- lib/util/identifier.js | 23 +- lib/validateSchema.js | 16 +- lib/wasm/WasmModuleTemplatePlugin.js | 147 +- lib/web/FetchCompileWasmMainTemplatePlugin.js | 161 ++- lib/web/FetchCompileWasmTemplatePlugin.js | 15 +- lib/web/JsonpChunkTemplatePlugin.js | 41 +- lib/web/JsonpExportMainTemplatePlugin.js | 23 +- lib/web/JsonpHotUpdateChunkTemplatePlugin.js | 38 +- lib/web/JsonpMainTemplate.runtime.js | 29 +- lib/web/JsonpMainTemplatePlugin.js | 598 ++++---- lib/web/JsonpTemplatePlugin.js | 6 +- lib/webpack.js | 147 +- lib/webpack.web.js | 7 +- lib/webworker/WebWorkerChunkTemplatePlugin.js | 26 +- .../WebWorkerHotUpdateChunkTemplatePlugin.js | 44 +- .../WebWorkerMainTemplate.runtime.js | 32 +- lib/webworker/WebWorkerMainTemplatePlugin.js | 210 +-- lib/webworker/WebWorkerTemplatePlugin.js | 15 +- test/BenchmarkTestCases.benchmark.js | 345 +++-- test/CachePlugin.unittest.js | 2 +- test/CaseSensitiveModulesWarning.unittest.js | 23 +- test/Chunk.unittest.js | 26 +- test/Compiler-caching.test.js | 315 ++-- test/Compiler.test.js | 68 +- test/ConfigTestCases.test.js | 184 ++- test/ContextModuleFactory.unittest.js | 46 +- test/DelegatedModule.unittest.js | 9 +- test/DependenciesBlockVariable.unittest.js | 21 +- test/Errors.test.js | 257 ++-- test/Examples.test.js | 38 +- test/ExternalModule.unittest.js | 61 +- ...ortImportedSpecifierDependency.unittest.js | 3 +- test/HotModuleReplacementPlugin.test.js | 45 +- test/HotTestCases.test.js | 132 +- test/Integration.test.js | 180 +-- test/LocalModulesHelpers.unittest.js | 46 +- test/ModuleDependencyError.unittest.js | 30 +- test/ModuleReason.unittest.js | 3 +- test/MultiCompiler.test.js | 21 +- test/MultiStats.unittest.js | 108 +- test/MultiWatching.unittest.js | 3 +- test/NodeTemplatePlugin.test.js | 134 +- test/NodeWatchFileSystem.unittest.js | 298 ++-- test/NormalModule.unittest.js | 108 +- test/NullDependency.unittest.js | 17 +- test/Parser.unittest.js | 335 +++-- test/ProfilingPlugin.unittest.js | 60 +- test/RawModule.unittest.js | 28 +- test/RuleSet.unittest.js | 593 ++++---- test/Schemas.lint.js | 49 +- test/SideEffectsFlagPlugin.unittest.js | 112 +- test/SizeFormatHelpers.unittest.js | 12 +- ...eMapDevToolModuleOptionsPlugin.unittest.js | 80 +- test/Stats.test.js | 52 +- test/Stats.unittest.js | 310 ++-- test/StatsTestCases.test.js | 93 +- test/Template.unittest.js | 10 +- test/TestCases.test.js | 458 +++--- test/Validation.test.js | 698 ++++----- test/WatchDetection.test.js | 62 +- test/WatchTestCases.test.js | 366 +++-- test/WatcherEvents.test.js | 23 +- test/WebEnvironmentPlugin.unittest.js | 12 +- test/WebpackMissingModule.unittest.js | 12 +- test/browsertest/webpack.config.js | 8 +- test/checkArrayExpectation.js | 83 +- test/compareLocations.unittest.js | 12 +- .../additional-pass/simple/webpack.config.js | 7 +- .../existing-name/webpack.config.js | 4 +- .../require-context-id/webpack.config.js | 4 +- .../hot-multi/webpack.config.js | 4 +- .../hot/webpack.config.js | 4 +- .../move-to-grandparent/webpack.config.js | 2 +- .../warn-not-found/webpack.config.js | 1 - .../simple/webpack.config.js | 4 +- .../System.import/webpack.config.js | 10 +- .../context-replacement/a/webpack.config.js | 7 +- .../context-replacement/c/webpack.config.js | 18 +- .../context-replacement/d/webpack.config.js | 22 +- .../xxhash/webpack.config.js | 10 +- .../dll-plugin/0-create-dll/webpack.config.js | 19 +- .../2-use-dll-without-scope/webpack.config.js | 22 +- .../3-use-dll-with-hashid/webpack.config.js | 24 +- .../webpack.config.js | 4 +- .../webpack.config.js | 1 - .../hashed-module-ids/webpack.config.js | 46 +- .../output-filename/webpack.config.js | 39 +- .../only-resource-context/webpack.config.js | 4 +- .../ignore/only-resource/webpack.config.js | 4 +- .../webpack.config.js | 4 +- .../resource-and-context/webpack.config.js | 4 +- .../0-create-library/webpack.config.js | 1 - .../library/1-use-library/webpack.config.js | 26 +- .../loaders/generate-ident/webpack.config.js | 5 +- .../loaders/hot-in-context/webpack.config.js | 17 +- .../loaders/issue-3320/webpack.config.js | 25 +- .../loaders/pre-post-loader/webpack.config.js | 3 +- .../remaining-request/webpack.config.js | 28 +- .../output/function/webpack.config.js | 2 +- .../parsing/extended-api/webpack.config.js | 4 +- .../harmony-this-concat/webpack.config.js | 4 +- .../parsing/system.import/webpack.config.js | 12 +- .../banner-plugin-hashing/webpack.config.js | 3 +- .../plugins/define-plugin/webpack.config.js | 6 +- .../environment-plugin/webpack.config.js | 103 +- .../lib-manifest-plugin/webpack.config.js | 5 +- .../plugins/progress-plugin/webpack.config.js | 17 +- .../plugins/provide-plugin/webpack.config.js | 4 +- .../webpack.config.js | 4 +- .../plugins/uglifyjs-plugin/webpack.config.js | 13 +- .../records/issue-295/webpack.config.js | 5 +- .../records/issue-2991/webpack.config.js | 5 +- .../rule-set/chaining/webpack.config.js | 1 - .../rule-set/compiler/webpack.config.js | 1 - .../rule-set/custom/webpack.config.js | 26 +- .../rule-set/query/webpack.config.js | 10 +- .../resolve-options/webpack.config.js | 14 +- .../simple-use-array-fn/webpack.config.js | 72 +- .../simple-use-fn-array/webpack.config.js | 50 +- .../rule-set/simple/webpack.config.js | 72 +- .../create-dll-plugin/webpack.config.js | 5 +- .../dll-plugin/webpack.config.js | 2 +- .../webpack.config.js | 4 +- .../side-effects-override/webpack.config.js | 3 +- .../simple/empty-config/webpack.config.js | 4 +- .../simple/multi-compiler/webpack.config.js | 4 +- .../source-map/nosources/webpack.config.js | 2 +- .../webpack.config.js | 2 +- .../target/buffer-default/webpack.config.js | 2 +- test/formatLocation.unittest.js | 166 ++- .../concat/reload-external/webpack.config.js | 4 +- test/hotPlayground/webpack.config.js | 4 +- test/identifier.unittest.js | 4 +- .../webpack.config.js | 15 +- .../webpack.config.js | 83 +- .../define-plugin/webpack.config.js | 2 - .../exclude-with-loader/webpack.config.js | 28 +- .../filter-warnings/webpack.config.js | 28 +- .../import-context-filter/webpack.config.js | 2 +- test/statsCases/import-weak/webpack.config.js | 2 +- .../webpack.config.js | 17 +- .../named-chunks-plugin/webpack.config.js | 7 +- .../preset-mixed-array/webpack.config.js | 2 - .../preset-none-array/webpack.config.js | 2 - .../resolve-plugin-context/webpack.config.js | 6 +- .../reverse-sort-modules/webpack.config.js | 2 +- .../scope-hoisting-multi/webpack.config.js | 2 - .../simple-more-info/webpack.config.js | 2 +- .../webpack.config.js | 2 +- .../statsCases/split-chunks/webpack.config.js | 2 - .../warnings-uglifyjs/webpack.config.js | 2 +- .../webpack.config.js | 4 +- .../dll-reference-plugin/webpack.config.js | 2 +- .../watch-ignore-plugin/webpack.config.js | 4 +- .../simple/multi-compiler/webpack.config.js | 27 +- 399 files changed, 19032 insertions(+), 12694 deletions(-) diff --git a/bin/webpack.js b/bin/webpack.js index 2431b35e6..22f08e0e7 100644 --- a/bin/webpack.js +++ b/bin/webpack.js @@ -4,15 +4,17 @@ let webpackCliInstalled = false; try { require.resolve("webpack-cli"); webpackCliInstalled = true; -} catch(e) { +} catch (e) { webpackCliInstalled = false; } -if(webpackCliInstalled) { +if (webpackCliInstalled) { require("webpack-cli"); // eslint-disable-line node/no-missing-require, node/no-extraneous-require, node/no-unpublished-require } else { console.error("The CLI moved into a separate package: webpack-cli."); - console.error("Please install 'webpack-cli' in addition to webpack itself to use the CLI."); + console.error( + "Please install 'webpack-cli' in addition to webpack itself to use the CLI." + ); console.error("-> When using npm: npm install webpack-cli -D"); console.error("-> When using yarn: yarn add webpack-cli -D"); process.exitCode = 1; diff --git a/buildin/global.js b/buildin/global.js index 8b23b86c7..35f3144e9 100644 --- a/buildin/global.js +++ b/buildin/global.js @@ -7,11 +7,10 @@ g = (function() { try { // This works if eval is allowed (see CSP) - g = g || Function("return this")() || (1,eval)("this"); -} catch(e) { + g = g || Function("return this")() || (1, eval)("this"); +} catch (e) { // This works if the window reference is available - if(typeof window === "object") - g = window; + if (typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... diff --git a/buildin/harmony-module.js b/buildin/harmony-module.js index 0f5678b27..c16146586 100644 --- a/buildin/harmony-module.js +++ b/buildin/harmony-module.js @@ -1,8 +1,8 @@ module.exports = function(originalModule) { - if(!originalModule.webpackPolyfill) { + if (!originalModule.webpackPolyfill) { var module = Object.create(originalModule); // module.parent = undefined by default - if(!module.children) module.children = []; + if (!module.children) module.children = []; Object.defineProperty(module, "loaded", { enumerable: true, get: function() { @@ -16,7 +16,7 @@ module.exports = function(originalModule) { } }); Object.defineProperty(module, "exports", { - enumerable: true, + enumerable: true }); module.webpackPolyfill = 1; } diff --git a/buildin/module.js b/buildin/module.js index 518a8c687..c92808b60 100644 --- a/buildin/module.js +++ b/buildin/module.js @@ -1,9 +1,9 @@ module.exports = function(module) { - if(!module.webpackPolyfill) { + if (!module.webpackPolyfill) { module.deprecate = function() {}; module.paths = []; // module.parent = undefined by default - if(!module.children) module.children = []; + if (!module.children) module.children = []; Object.defineProperty(module, "loaded", { enumerable: true, get: function() { diff --git a/examples/coffee-script/webpack.config.js b/examples/coffee-script/webpack.config.js index 812cb3241..845f9f4c1 100644 --- a/examples/coffee-script/webpack.config.js +++ b/examples/coffee-script/webpack.config.js @@ -1,10 +1,12 @@ module.exports = { // mode: "development || "production", module: { - rules: [{ - test: /\.coffee$/, - loader: "coffee-loader" - }] + rules: [ + { + test: /\.coffee$/, + loader: "coffee-loader" + } + ] }, resolve: { extensions: [".web.coffee", ".web.js", ".coffee", ".js"] diff --git a/examples/dll-app-and-vendor/0-vendor/webpack.config.js b/examples/dll-app-and-vendor/0-vendor/webpack.config.js index 3c56c5ccf..ec5f19b19 100644 --- a/examples/dll-app-and-vendor/0-vendor/webpack.config.js +++ b/examples/dll-app-and-vendor/0-vendor/webpack.config.js @@ -8,12 +8,12 @@ module.exports = { output: { filename: "vendor.js", // best use [hash] here too path: path.resolve(__dirname, "dist"), - library: "vendor_lib_[hash]", + library: "vendor_lib_[hash]" }, plugins: [ new webpack.DllPlugin({ name: "vendor_lib_[hash]", - path: path.resolve(__dirname, "dist/vendor-manifest.json"), - }), - ], + path: path.resolve(__dirname, "dist/vendor-manifest.json") + }) + ] }; diff --git a/examples/dll-app-and-vendor/1-app/webpack.config.js b/examples/dll-app-and-vendor/1-app/webpack.config.js index 0b45b7d07..2f43dacef 100644 --- a/examples/dll-app-and-vendor/1-app/webpack.config.js +++ b/examples/dll-app-and-vendor/1-app/webpack.config.js @@ -7,12 +7,12 @@ module.exports = { entry: "./example-app", output: { filename: "app.js", - path: path.resolve(__dirname, "dist"), + path: path.resolve(__dirname, "dist") }, plugins: [ new webpack.DllReferencePlugin({ context: ".", - manifest: require("../0-vendor/dist/vendor-manifest.json"), // eslint-disable-line - }), - ], + manifest: require("../0-vendor/dist/vendor-manifest.json") // eslint-disable-line + }) + ] }; diff --git a/examples/explicit-vendor-chunk/webpack.config.js b/examples/explicit-vendor-chunk/webpack.config.js index 40fa5c108..e924b3acd 100644 --- a/examples/explicit-vendor-chunk/webpack.config.js +++ b/examples/explicit-vendor-chunk/webpack.config.js @@ -1,7 +1,6 @@ var path = require("path"); var webpack = require("../../"); module.exports = [ - { name: "vendor", // mode: "development || "production", @@ -38,5 +37,4 @@ module.exports = [ }) ] } - ]; diff --git a/examples/externals/webpack.config.js b/examples/externals/webpack.config.js index 2375d32ab..8210f6627 100644 --- a/examples/externals/webpack.config.js +++ b/examples/externals/webpack.config.js @@ -6,7 +6,7 @@ module.exports = { externals: [ "add", { - "subtract": { + subtract: { root: "subtract", commonjs2: "./subtract", commonjs: ["./math", "subtract"], diff --git a/examples/hybrid-routing/webpack.config.js b/examples/hybrid-routing/webpack.config.js index f79a5b81e..7a6bbafe2 100644 --- a/examples/hybrid-routing/webpack.config.js +++ b/examples/hybrid-routing/webpack.config.js @@ -5,7 +5,7 @@ module.exports = { // The entry points for the pages // They also contains router pageA: ["./aEntry", "./router"], - pageB: ["./bEntry", "./router"], + pageB: ["./bEntry", "./router"] }, output: { path: path.join(__dirname, "dist"), diff --git a/examples/i18n/webpack.config.js b/examples/i18n/webpack.config.js index da52d4b8f..cc0267fa9 100644 --- a/examples/i18n/webpack.config.js +++ b/examples/i18n/webpack.config.js @@ -1,8 +1,8 @@ var path = require("path"); var I18nPlugin = require("i18n-webpack-plugin"); var languages = { - "en": null, - "de": require("./de.json") + en: null, + de: require("./de.json") }; module.exports = Object.keys(languages).map(function(language) { return { @@ -13,10 +13,6 @@ module.exports = Object.keys(languages).map(function(language) { path: path.join(__dirname, "dist"), filename: language + ".output.js" }, - plugins: [ - new I18nPlugin( - languages[language] - ) - ] + plugins: [new I18nPlugin(languages[language])] }; }); diff --git a/examples/loader/webpack.config.js b/examples/loader/webpack.config.js index 29a561f00..73f1713f0 100644 --- a/examples/loader/webpack.config.js +++ b/examples/loader/webpack.config.js @@ -1,9 +1,11 @@ module.exports = { // mode: "development || "production", module: { - rules: [{ - test: /\.css$/, - loader: "css-loader" - }] + rules: [ + { + test: /\.css$/, + loader: "css-loader" + } + ] } }; diff --git a/examples/multi-compiler/webpack.config.js b/examples/multi-compiler/webpack.config.js index 354430156..4fc308863 100644 --- a/examples/multi-compiler/webpack.config.js +++ b/examples/multi-compiler/webpack.config.js @@ -1,7 +1,6 @@ var path = require("path"); var webpack = require("../../"); module.exports = [ - { name: "mobile", // mode: "development || "production", @@ -31,5 +30,4 @@ module.exports = [ }) ] } - ]; diff --git a/examples/source-map/webpack.config.js b/examples/source-map/webpack.config.js index 9d6e6aea0..7e76cf81b 100644 --- a/examples/source-map/webpack.config.js +++ b/examples/source-map/webpack.config.js @@ -10,15 +10,15 @@ module.exports = [ "hidden-source-map", "inline-source-map", "nosources-source-map", - "source-map", + "source-map" ].map(devtool => ({ mode: "development", entry: { - bundle: "coffee-loader!./example.coffee", + bundle: "coffee-loader!./example.coffee" }, output: { path: path.join(__dirname, "dist"), - filename: `./[name]-${devtool}.js`, + filename: `./[name]-${devtool}.js` }, devtool, optimization: { diff --git a/examples/wasm-simple/webpack.config.js b/examples/wasm-simple/webpack.config.js index f7b8ed4cd..df7a7e90c 100644 --- a/examples/wasm-simple/webpack.config.js +++ b/examples/wasm-simple/webpack.config.js @@ -5,10 +5,12 @@ module.exports = { publicPath: "js/" }, module: { - rules: [{ - test: /\.wasm$/, - type: "webassembly/experimental" - }] + rules: [ + { + test: /\.wasm$/, + type: "webassembly/experimental" + } + ] }, optimization: { occurrenceOrder: true // To keep filename consistent between different modes (for example building only) diff --git a/hot/.eslintrc b/hot/.eslintrc index 787588323..e35b431db 100644 --- a/hot/.eslintrc +++ b/hot/.eslintrc @@ -5,5 +5,4 @@ "rules": { "node/exports-style": ["off"] } - } diff --git a/hot/dev-server.js b/hot/dev-server.js index 54c6eed28..a4cb0f50d 100644 --- a/hot/dev-server.js +++ b/hot/dev-server.js @@ -3,46 +3,54 @@ Author Tobias Koppers @sokra */ /*globals window __webpack_hash__ */ -if(module.hot) { +if (module.hot) { var lastHash; var upToDate = function upToDate() { return lastHash.indexOf(__webpack_hash__) >= 0; }; var log = require("./log"); var check = function check() { - module.hot.check(true).then(function(updatedModules) { - if(!updatedModules) { - log("warning", "[HMR] Cannot find update. Need to do a full reload!"); - log("warning", "[HMR] (Probably because of restarting the webpack-dev-server)"); - window.location.reload(); - return; - } + module.hot + .check(true) + .then(function(updatedModules) { + if (!updatedModules) { + log("warning", "[HMR] Cannot find update. Need to do a full reload!"); + log( + "warning", + "[HMR] (Probably because of restarting the webpack-dev-server)" + ); + window.location.reload(); + return; + } - if(!upToDate()) { - check(); - } + if (!upToDate()) { + check(); + } - require("./log-apply-result")(updatedModules, updatedModules); + require("./log-apply-result")(updatedModules, updatedModules); - if(upToDate()) { - log("info", "[HMR] App is up to date."); - } - - }).catch(function(err) { - var status = module.hot.status(); - if(["abort", "fail"].indexOf(status) >= 0) { - log("warning", "[HMR] Cannot apply update. Need to do a full reload!"); - log("warning", "[HMR] " + err.stack || err.message); - window.location.reload(); - } else { - log("warning", "[HMR] Update failed: " + err.stack || err.message); - } - }); + if (upToDate()) { + log("info", "[HMR] App is up to date."); + } + }) + .catch(function(err) { + var status = module.hot.status(); + if (["abort", "fail"].indexOf(status) >= 0) { + log( + "warning", + "[HMR] Cannot apply update. Need to do a full reload!" + ); + log("warning", "[HMR] " + err.stack || err.message); + window.location.reload(); + } else { + log("warning", "[HMR] Update failed: " + err.stack || err.message); + } + }); }; var hotEmitter = require("./emitter"); hotEmitter.on("webpackHotUpdate", function(currentHash) { lastHash = currentHash; - if(!upToDate() && module.hot.status() === "idle") { + if (!upToDate() && module.hot.status() === "idle") { log("info", "[HMR] Checking for updates on the server..."); check(); } diff --git a/hot/log-apply-result.js b/hot/log-apply-result.js index a795cc593..b63e75741 100644 --- a/hot/log-apply-result.js +++ b/hot/log-apply-result.js @@ -8,19 +8,22 @@ module.exports = function(updatedModules, renewedModules) { }); var log = require("./log"); - if(unacceptedModules.length > 0) { - log("warning", "[HMR] The following modules couldn't be hot updated: (They would need a full reload!)"); + if (unacceptedModules.length > 0) { + log( + "warning", + "[HMR] The following modules couldn't be hot updated: (They would need a full reload!)" + ); unacceptedModules.forEach(function(moduleId) { log("warning", "[HMR] - " + moduleId); }); } - if(!renewedModules || renewedModules.length === 0) { + if (!renewedModules || renewedModules.length === 0) { log("info", "[HMR] Nothing hot updated."); } else { log("info", "[HMR] Updated modules:"); renewedModules.forEach(function(moduleId) { - if(typeof moduleId === "string" && moduleId.indexOf("!") !== -1) { + if (typeof moduleId === "string" && moduleId.indexOf("!") !== -1) { var parts = moduleId.split("!"); log.groupCollapsed("info", "[HMR] - " + parts.pop()); log("info", "[HMR] - " + moduleId); @@ -32,7 +35,10 @@ module.exports = function(updatedModules, renewedModules) { var numberIds = renewedModules.every(function(moduleId) { return typeof moduleId === "number"; }); - if(numberIds) - log("info", "[HMR] Consider using the NamedModulesPlugin for module names."); + if (numberIds) + log( + "info", + "[HMR] Consider using the NamedModulesPlugin for module names." + ); } }; diff --git a/hot/log.js b/hot/log.js index 2baf6ccee..d9e09b221 100644 --- a/hot/log.js +++ b/hot/log.js @@ -3,7 +3,8 @@ var logLevel = "info"; function dummy() {} function shouldLog(level) { - var shouldLog = (logLevel === "info" && level === "info") || + var shouldLog = + (logLevel === "info" && level === "info") || (["info", "warning"].indexOf(logLevel) >= 0 && level === "warning") || (["info", "warning", "error"].indexOf(logLevel) >= 0 && level === "error"); return shouldLog; @@ -11,19 +12,19 @@ function shouldLog(level) { function logGroup(logFn) { return function(level, msg) { - if(shouldLog(level)) { + if (shouldLog(level)) { logFn(msg); } }; } module.exports = function(level, msg) { - if(shouldLog(level)) { - if(level === "info") { + if (shouldLog(level)) { + if (level === "info") { console.log(msg); - } else if(level === "warning") { + } else if (level === "warning") { console.warn(msg); - } else if(level === "error") { + } else if (level === "error") { console.error(msg); } } diff --git a/hot/only-dev-server.js b/hot/only-dev-server.js index 0ad41eee6..cf452dc6e 100644 --- a/hot/only-dev-server.js +++ b/hot/only-dev-server.js @@ -3,65 +3,99 @@ Author Tobias Koppers @sokra */ /*globals __webpack_hash__ */ -if(module.hot) { +if (module.hot) { var lastHash; var upToDate = function upToDate() { return lastHash.indexOf(__webpack_hash__) >= 0; }; var log = require("./log"); var check = function check() { - module.hot.check().then(function(updatedModules) { - if(!updatedModules) { - log("warning", "[HMR] Cannot find update. Need to do a full reload!"); - log("warning", "[HMR] (Probably because of restarting the webpack-dev-server)"); - return; - } - - return module.hot.apply({ - ignoreUnaccepted: true, - ignoreDeclined: true, - ignoreErrored: true, - onUnaccepted: function(data) { - log("warning", "Ignored an update to unaccepted module " + data.chain.join(" -> ")); - }, - onDeclined: function(data) { - log("warning", "Ignored an update to declined module " + data.chain.join(" -> ")); - }, - onErrored: function(data) { - log("error", data.error); - log("warning", "Ignored an error while updating module " + data.moduleId + " (" + data.type + ")"); - } - }).then(function(renewedModules) { - if(!upToDate()) { - check(); + module.hot + .check() + .then(function(updatedModules) { + if (!updatedModules) { + log("warning", "[HMR] Cannot find update. Need to do a full reload!"); + log( + "warning", + "[HMR] (Probably because of restarting the webpack-dev-server)" + ); + return; } - require("./log-apply-result")(updatedModules, renewedModules); + return module.hot + .apply({ + ignoreUnaccepted: true, + ignoreDeclined: true, + ignoreErrored: true, + onUnaccepted: function(data) { + log( + "warning", + "Ignored an update to unaccepted module " + + data.chain.join(" -> ") + ); + }, + onDeclined: function(data) { + log( + "warning", + "Ignored an update to declined module " + + data.chain.join(" -> ") + ); + }, + onErrored: function(data) { + log("error", data.error); + log( + "warning", + "Ignored an error while updating module " + + data.moduleId + + " (" + + data.type + + ")" + ); + } + }) + .then(function(renewedModules) { + if (!upToDate()) { + check(); + } - if(upToDate()) { - log("info", "[HMR] App is up to date."); + require("./log-apply-result")(updatedModules, renewedModules); + + if (upToDate()) { + log("info", "[HMR] App is up to date."); + } + }); + }) + .catch(function(err) { + var status = module.hot.status(); + if (["abort", "fail"].indexOf(status) >= 0) { + log( + "warning", + "[HMR] Cannot check for update. Need to do a full reload!" + ); + log("warning", "[HMR] " + err.stack || err.message); + } else { + log( + "warning", + "[HMR] Update check failed: " + err.stack || err.message + ); } }); - }).catch(function(err) { - var status = module.hot.status(); - if(["abort", "fail"].indexOf(status) >= 0) { - log("warning", "[HMR] Cannot check for update. Need to do a full reload!"); - log("warning", "[HMR] " + err.stack || err.message); - } else { - log("warning", "[HMR] Update check failed: " + err.stack || err.message); - } - }); }; var hotEmitter = require("./emitter"); hotEmitter.on("webpackHotUpdate", function(currentHash) { lastHash = currentHash; - if(!upToDate()) { + if (!upToDate()) { var status = module.hot.status(); - if(status === "idle") { + if (status === "idle") { log("info", "[HMR] Checking for updates on the server..."); check(); - } else if(["abort", "fail"].indexOf(status) >= 0) { - log("warning", "[HMR] Cannot apply update as a previous update " + status + "ed. Need to do a full reload!"); + } else if (["abort", "fail"].indexOf(status) >= 0) { + log( + "warning", + "[HMR] Cannot apply update as a previous update " + + status + + "ed. Need to do a full reload!" + ); } } }); diff --git a/hot/poll.js b/hot/poll.js index 5a075f677..f615accef 100644 --- a/hot/poll.js +++ b/hot/poll.js @@ -3,29 +3,32 @@ Author Tobias Koppers @sokra */ /*globals __resourceQuery */ -if(module.hot) { - var hotPollInterval = +(__resourceQuery.substr(1)) || (10 * 60 * 1000); +if (module.hot) { + var hotPollInterval = +__resourceQuery.substr(1) || 10 * 60 * 1000; var log = require("./log"); var checkForUpdate = function checkForUpdate(fromUpdate) { - if(module.hot.status() === "idle") { - module.hot.check(true).then(function(updatedModules) { - if(!updatedModules) { - if(fromUpdate) log("info", "[HMR] Update applied."); - return; - } - require("./log-apply-result")(updatedModules, updatedModules); - checkForUpdate(true); - }).catch(function(err) { - var status = module.hot.status(); - if(["abort", "fail"].indexOf(status) >= 0) { - log("warning", "[HMR] Cannot apply update."); - log("warning", "[HMR] " + err.stack || err.message); - log("warning", "[HMR] You need to restart the application!"); - } else { - log("warning", "[HMR] Update failed: " + err.stack || err.message); - } - }); + if (module.hot.status() === "idle") { + module.hot + .check(true) + .then(function(updatedModules) { + if (!updatedModules) { + if (fromUpdate) log("info", "[HMR] Update applied."); + return; + } + require("./log-apply-result")(updatedModules, updatedModules); + checkForUpdate(true); + }) + .catch(function(err) { + var status = module.hot.status(); + if (["abort", "fail"].indexOf(status) >= 0) { + log("warning", "[HMR] Cannot apply update."); + log("warning", "[HMR] " + err.stack || err.message); + log("warning", "[HMR] You need to restart the application!"); + } else { + log("warning", "[HMR] Update failed: " + err.stack || err.message); + } + }); } }; setInterval(checkForUpdate, hotPollInterval); diff --git a/hot/signal.js b/hot/signal.js index 2dfa88671..d3ce50e8c 100644 --- a/hot/signal.js +++ b/hot/signal.js @@ -3,44 +3,54 @@ Author Tobias Koppers @sokra */ /*globals __resourceQuery */ -if(module.hot) { +if (module.hot) { var log = require("./log"); var checkForUpdate = function checkForUpdate(fromUpdate) { - module.hot.check().then(function(updatedModules) { - if(!updatedModules) { - if(fromUpdate) - log("info", "[HMR] Update applied."); - else - log("warning", "[HMR] Cannot find update."); - return; - } + module.hot + .check() + .then(function(updatedModules) { + if (!updatedModules) { + if (fromUpdate) log("info", "[HMR] Update applied."); + else log("warning", "[HMR] Cannot find update."); + return; + } - return module.hot.apply({ - ignoreUnaccepted: true, - onUnaccepted: function(data) { - log("warning", "Ignored an update to unaccepted module " + data.chain.join(" -> ")); - }, - }).then(function(renewedModules) { - require("./log-apply-result")(updatedModules, renewedModules); + return module.hot + .apply({ + ignoreUnaccepted: true, + onUnaccepted: function(data) { + log( + "warning", + "Ignored an update to unaccepted module " + + data.chain.join(" -> ") + ); + } + }) + .then(function(renewedModules) { + require("./log-apply-result")(updatedModules, renewedModules); - checkForUpdate(true); - return null; + checkForUpdate(true); + return null; + }); + }) + .catch(function(err) { + var status = module.hot.status(); + if (["abort", "fail"].indexOf(status) >= 0) { + log("warning", "[HMR] Cannot apply update."); + log("warning", "[HMR] " + err.stack || err.message); + log("warning", "[HMR] You need to restart the application!"); + } else { + log("warning", "[HMR] Update failed: " + err.stack || err.message); + } }); - }).catch(function(err) { - var status = module.hot.status(); - if(["abort", "fail"].indexOf(status) >= 0) { - log("warning", "[HMR] Cannot apply update."); - log("warning", "[HMR] " + err.stack || err.message); - log("warning", "[HMR] You need to restart the application!"); - } else { - log("warning", "[HMR] Update failed: " + err.stack || err.message); - } - }); }; process.on(__resourceQuery.substr(1) || "SIGUSR2", function() { - if(module.hot.status() !== "idle") { - log("warning", "[HMR] Got signal but currently in " + module.hot.status() + " state."); + if (module.hot.status() !== "idle") { + log( + "warning", + "[HMR] Got signal but currently in " + module.hot.status() + " state." + ); log("warning", "[HMR] Need to be in idle state to start hot update."); return; } diff --git a/lib/APIPlugin.js b/lib/APIPlugin.js index b2314728a..ad8980cb9 100644 --- a/lib/APIPlugin.js +++ b/lib/APIPlugin.js @@ -33,23 +33,51 @@ const REPLACEMENT_TYPES = { class APIPlugin { apply(compiler) { - compiler.hooks.compilation.tap("APIPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compiler.hooks.compilation.tap( + "APIPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - const handler = parser => { - Object.keys(REPLACEMENTS).forEach(key => { - parser.hooks.expression.for(key).tap("APIPlugin", NO_WEBPACK_REQUIRE[key] ? ParserHelpers.toConstantDependency(parser, REPLACEMENTS[key]) : ParserHelpers.toConstantDependencyWithWebpackRequire(parser, REPLACEMENTS[key])); - parser.hooks.evaluateTypeof.for(key).tap("APIPlugin", ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])); - }); - }; + const handler = parser => { + Object.keys(REPLACEMENTS).forEach(key => { + parser.hooks.expression + .for(key) + .tap( + "APIPlugin", + NO_WEBPACK_REQUIRE[key] + ? ParserHelpers.toConstantDependency( + parser, + REPLACEMENTS[key] + ) + : ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + REPLACEMENTS[key] + ) + ); + parser.hooks.evaluateTypeof + .for(key) + .tap( + "APIPlugin", + ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key]) + ); + }); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("APIPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("APIPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("APIPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("APIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("APIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("APIPlugin", handler); + } + ); } } diff --git a/lib/AmdMainTemplatePlugin.js b/lib/AmdMainTemplatePlugin.js index 8cd744493..fe63c23b1 100644 --- a/lib/AmdMainTemplatePlugin.js +++ b/lib/AmdMainTemplatePlugin.js @@ -14,42 +14,56 @@ class AmdMainTemplatePlugin { } apply(compilation) { - const { - mainTemplate, - chunkTemplate - } = compilation; + const { mainTemplate, chunkTemplate } = compilation; const onRenderWithEntry = (source, chunk, hash) => { - const externals = chunk.getModules().filter((m) => m.external); - const externalsDepsArray = JSON.stringify(externals.map((m) => - typeof m.request === "object" ? m.request.amd : m.request - )); - const externalsArguments = externals.map((m) => - `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__` - ).join(", "); + const externals = chunk.getModules().filter(m => m.external); + const externalsDepsArray = JSON.stringify( + externals.map( + m => (typeof m.request === "object" ? m.request.amd : m.request) + ) + ); + const externalsArguments = externals + .map( + m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__` + ) + .join(", "); - if(this.name) { + if (this.name) { const name = mainTemplate.getAssetPath(this.name, { hash, chunk }); return new ConcatSource( - `define(${JSON.stringify(name)}, ${externalsDepsArray}, function(${externalsArguments}) { return `, source, "});" + `define(${JSON.stringify(name)}, ${externalsDepsArray}, function(${ + externalsArguments + }) { return `, + source, + "});" + ); + } else if (externalsArguments) { + return new ConcatSource( + `define(${externalsDepsArray}, function(${ + externalsArguments + }) { return `, + source, + "});" ); - } else if(externalsArguments) { - return new ConcatSource(`define(${externalsDepsArray}, function(${externalsArguments}) { return `, source, "});"); } else { return new ConcatSource("define(function() { return ", source, "});"); } }; - for(const template of [mainTemplate, chunkTemplate]) { - template.hooks.renderWithEntry.tap("AmdMainTemplatePlugin", onRenderWithEntry); + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "AmdMainTemplatePlugin", + onRenderWithEntry + ); } mainTemplate.hooks.globalHashPaths.tap("AmdMainTemplatePlugin", paths => { - if(this.name) paths.push(this.name); + if (this.name) paths.push(this.name); return paths; }); diff --git a/lib/AsyncDependenciesBlock.js b/lib/AsyncDependenciesBlock.js index e06eea42e..806d84970 100644 --- a/lib/AsyncDependenciesBlock.js +++ b/lib/AsyncDependenciesBlock.js @@ -25,9 +25,15 @@ module.exports = class AsyncDependenciesBlock extends DependenciesBlock { updateHash(hash) { hash.update(this.chunkName || ""); - hash.update(this.chunkGroup && this.chunkGroup.chunks.map(chunk => { - return chunk.id !== null ? chunk.id : ""; - }).join(",") || ""); + hash.update( + (this.chunkGroup && + this.chunkGroup.chunks + .map(chunk => { + return chunk.id !== null ? chunk.id : ""; + }) + .join(",")) || + "" + ); super.updateHash(hash); } diff --git a/lib/AsyncDependencyToInitialChunkError.js b/lib/AsyncDependencyToInitialChunkError.js index 723cf08bb..168123f1a 100644 --- a/lib/AsyncDependencyToInitialChunkError.js +++ b/lib/AsyncDependencyToInitialChunkError.js @@ -11,7 +11,9 @@ module.exports = class AsyncDependencyToInitialChunkError extends WebpackError { super(); this.name = "AsyncDependencyToInitialChunkError"; - this.message = `It's not allowed to load an initial chunk on demand. The chunk name "${chunkName}" is already used by an entrypoint.`; + this.message = `It's not allowed to load an initial chunk on demand. The chunk name "${ + chunkName + }" is already used by an entrypoint.`; this.module = module; this.origin = module; this.originLoc = loc; diff --git a/lib/AutomaticPrefetchPlugin.js b/lib/AutomaticPrefetchPlugin.js index fd0c75609..4efb350ce 100644 --- a/lib/AutomaticPrefetchPlugin.js +++ b/lib/AutomaticPrefetchPlugin.js @@ -10,13 +10,17 @@ const NormalModule = require("./NormalModule"); class AutomaticPrefetchPlugin { apply(compiler) { - compiler.hooks.compilation.tap("AutomaticPrefetchPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(PrefetchDependency, normalModuleFactory); - }); + compiler.hooks.compilation.tap( + "AutomaticPrefetchPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + PrefetchDependency, + normalModuleFactory + ); + } + ); let lastModules = null; - compiler.hooks.afterCompile.tap("AutomaticPrefetchPlugin", (compilation) => { + compiler.hooks.afterCompile.tap("AutomaticPrefetchPlugin", compilation => { lastModules = compilation.modules .filter(m => m instanceof NormalModule) .map(m => ({ @@ -24,12 +28,23 @@ class AutomaticPrefetchPlugin { request: m.request })); }); - compiler.hooks.make.tapAsync("AutomaticPrefetchPlugin", (compilation, callback) => { - if(!lastModules) return callback(); - asyncLib.forEach(lastModules, (m, callback) => { - compilation.prefetch(m.context || compiler.context, new PrefetchDependency(m.request), callback); - }, callback); - }); + compiler.hooks.make.tapAsync( + "AutomaticPrefetchPlugin", + (compilation, callback) => { + if (!lastModules) return callback(); + asyncLib.forEach( + lastModules, + (m, callback) => { + compilation.prefetch( + m.context || compiler.context, + new PrefetchDependency(m.request), + callback + ); + }, + callback + ); + } + ); } } module.exports = AutomaticPrefetchPlugin; diff --git a/lib/BannerPlugin.js b/lib/BannerPlugin.js index f54e91920..97e383ceb 100644 --- a/lib/BannerPlugin.js +++ b/lib/BannerPlugin.js @@ -12,40 +12,50 @@ const Template = require("./Template"); const validateOptions = require("schema-utils"); const schema = require("../schemas/plugins/BannerPlugin.json"); -const wrapComment = (str) => { - if(!str.includes("\n")) return Template.toComment(str); - return `/*!\n * ${str.replace(/\*\//g, "* /").split("\n").join("\n * ")}\n */`; +const wrapComment = str => { + if (!str.includes("\n")) return Template.toComment(str); + return `/*!\n * ${str + .replace(/\*\//g, "* /") + .split("\n") + .join("\n * ")}\n */`; }; class BannerPlugin { constructor(options) { - if(arguments.length > 1) - throw new Error("BannerPlugin only takes one argument (pass an options object)"); + if (arguments.length > 1) + throw new Error( + "BannerPlugin only takes one argument (pass an options object)" + ); validateOptions(schema, options, "Banner Plugin"); - if(typeof options === "string") + if (typeof options === "string") options = { banner: options }; this.options = options || {}; - this.banner = this.options.raw ? options.banner : wrapComment(options.banner); + this.banner = this.options.raw + ? options.banner + : wrapComment(options.banner); } apply(compiler) { const options = this.options; const banner = this.banner; - const matchObject = ModuleFilenameHelpers.matchObject.bind(undefined, options); + const matchObject = ModuleFilenameHelpers.matchObject.bind( + undefined, + options + ); - compiler.hooks.compilation.tap("BannerPlugin", (compilation) => { - compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", (chunks) => { - for(const chunk of chunks) { - if(options.entryOnly && !chunk.canBeInitial()) { + compiler.hooks.compilation.tap("BannerPlugin", compilation => { + compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", chunks => { + for (const chunk of chunks) { + if (options.entryOnly && !chunk.canBeInitial()) { continue; } - for(const file of chunk.files) { - if(!matchObject(file)) { + for (const file of chunk.files) { + if (!matchObject(file)) { continue; } @@ -55,14 +65,14 @@ class BannerPlugin { const hash = compilation.hash; const querySplit = filename.indexOf("?"); - if(querySplit >= 0) { + if (querySplit >= 0) { query = filename.substr(querySplit); filename = filename.substr(0, querySplit); } const lastSlashIndex = filename.lastIndexOf("/"); - if(lastSlashIndex === -1) { + if (lastSlashIndex === -1) { basename = filename; } else { basename = filename.substr(lastSlashIndex + 1); @@ -73,10 +83,14 @@ class BannerPlugin { chunk, filename, basename, - query, + query }); - compilation.assets[file] = new ConcatSource(comment, "\n", compilation.assets[file]); + compilation.assets[file] = new ConcatSource( + comment, + "\n", + compilation.assets[file] + ); } } }); diff --git a/lib/BasicEvaluatedExpression.js b/lib/BasicEvaluatedExpression.js index 4815ecc20..48134eae0 100644 --- a/lib/BasicEvaluatedExpression.js +++ b/lib/BasicEvaluatedExpression.js @@ -19,7 +19,6 @@ const TypeWrapped = 10; const TypeTemplateString = 11; class BasicEvaluatedExpression { - constructor() { this.type = TypeUnknown; this.range = null; @@ -90,19 +89,23 @@ class BasicEvaluatedExpression { } asBool() { - if(this.truthy) return true; - else if(this.falsy) return false; - else if(this.isBoolean()) return this.bool; - else if(this.isNull()) return false; - else if(this.isString()) return this.string !== ""; - else if(this.isNumber()) return this.number !== 0; - else if(this.isRegExp()) return true; - else if(this.isArray()) return true; - else if(this.isConstArray()) return true; - else if(this.isWrapped()) return this.prefix && this.prefix.asBool() || this.postfix && this.postfix.asBool() ? true : undefined; - else if(this.isTemplateString()) { - for(const quasi of this.quasis) { - if(quasi.asBool()) return true; + if (this.truthy) return true; + else if (this.falsy) return false; + else if (this.isBoolean()) return this.bool; + else if (this.isNull()) return false; + else if (this.isString()) return this.string !== ""; + else if (this.isNumber()) return this.number !== 0; + else if (this.isRegExp()) return true; + else if (this.isArray()) return true; + else if (this.isConstArray()) return true; + else if (this.isWrapped()) + return (this.prefix && this.prefix.asBool()) || + (this.postfix && this.postfix.asBool()) + ? true + : undefined; + else if (this.isTemplateString()) { + for (const quasi of this.quasis) { + if (quasi.asBool()) return true; } // can't tell if string will be empty without executing } @@ -158,12 +161,11 @@ class BasicEvaluatedExpression { } addOptions(options) { - if(!this.options) { + if (!this.options) { this.type = TypeConditional; this.options = []; } - for(const item of options) - this.options.push(item); + for (const item of options) this.options.push(item); return this; } @@ -201,7 +203,6 @@ class BasicEvaluatedExpression { this.range = range; return this; } - } module.exports = BasicEvaluatedExpression; diff --git a/lib/CachePlugin.js b/lib/CachePlugin.js index 6409fcdfc..7a16df101 100644 --- a/lib/CachePlugin.js +++ b/lib/CachePlugin.js @@ -13,26 +13,29 @@ class CachePlugin { } apply(compiler) { - if(Array.isArray(compiler.compilers)) { + if (Array.isArray(compiler.compilers)) { compiler.compilers.forEach((c, idx) => { - new CachePlugin(this.cache[idx] = this.cache[idx] || {}).apply(c); + new CachePlugin((this.cache[idx] = this.cache[idx] || {})).apply(c); }); } else { const registerCacheToCompiler = (compiler, cache) => { compiler.hooks.thisCompilation.tap("CachePlugin", compilation => { compilation.cache = cache; - compilation.hooks.childCompiler.tap("CachePlugin", (childCompiler, compilerName, compilerIndex) => { - if(cache) { - let childCache; - if(!cache.children) cache.children = {}; - if(!cache.children[compilerName]) cache.children[compilerName] = []; - if(cache.children[compilerName][compilerIndex]) - childCache = cache.children[compilerName][compilerIndex]; - else - cache.children[compilerName].push(childCache = {}); - registerCacheToCompiler(childCompiler, childCache); + compilation.hooks.childCompiler.tap( + "CachePlugin", + (childCompiler, compilerName, compilerIndex) => { + if (cache) { + let childCache; + if (!cache.children) cache.children = {}; + if (!cache.children[compilerName]) + cache.children[compilerName] = []; + if (cache.children[compilerName][compilerIndex]) + childCache = cache.children[compilerName][compilerIndex]; + else cache.children[compilerName].push((childCache = {})); + registerCacheToCompiler(childCompiler, childCache); + } } - }); + ); }); }; registerCacheToCompiler(compiler, this.cache); @@ -40,49 +43,52 @@ class CachePlugin { this.watching = true; }); compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => { - if(!compiler._lastCompilationFileDependencies) return callback(); + if (!compiler._lastCompilationFileDependencies) return callback(); const fs = compiler.inputFileSystem; - const fileTs = compiler.fileTimestamps = new Map(); - asyncLib.forEach(compiler._lastCompilationFileDependencies, (file, callback) => { - fs.stat(file, (err, stat) => { - if(err) { - if(err.code === "ENOENT") return callback(); - return callback(err); + const fileTs = (compiler.fileTimestamps = new Map()); + asyncLib.forEach( + compiler._lastCompilationFileDependencies, + (file, callback) => { + fs.stat(file, (err, stat) => { + if (err) { + if (err.code === "ENOENT") return callback(); + return callback(err); + } + + if (stat.mtime) this.applyMtime(+stat.mtime); + + fileTs.set(file, +stat.mtime || Infinity); + + callback(); + }); + }, + err => { + if (err) return callback(err); + + for (const [file, ts] of fileTs) { + fileTs.set(file, ts + this.FS_ACCURACY); } - if(stat.mtime) - this.applyMtime(+stat.mtime); - - fileTs.set(file, +stat.mtime || Infinity); - callback(); - }); - }, err => { - if(err) return callback(err); - - for(const [file, ts] of fileTs) { - fileTs.set(file, ts + this.FS_ACCURACY); } - - callback(); - }); + ); }); compiler.hooks.afterCompile.tap("CachePlugin", compilation => { - compilation.compiler._lastCompilationFileDependencies = compilation.fileDependencies; - compilation.compiler._lastCompilationContextDependencies = compilation.contextDependencies; + compilation.compiler._lastCompilationFileDependencies = + compilation.fileDependencies; + compilation.compiler._lastCompilationContextDependencies = + compilation.contextDependencies; }); } } /* istanbul ignore next */ applyMtime(mtime) { - if(this.FS_ACCURACY > 1 && mtime % 2 !== 0) - this.FS_ACCURACY = 1; - else if(this.FS_ACCURACY > 10 && mtime % 20 !== 0) - this.FS_ACCURACY = 10; - else if(this.FS_ACCURACY > 100 && mtime % 200 !== 0) + if (this.FS_ACCURACY > 1 && mtime % 2 !== 0) this.FS_ACCURACY = 1; + else if (this.FS_ACCURACY > 10 && mtime % 20 !== 0) this.FS_ACCURACY = 10; + else if (this.FS_ACCURACY > 100 && mtime % 200 !== 0) this.FS_ACCURACY = 100; - else if(this.FS_ACCURACY > 1000 && mtime % 2000 !== 0) + else if (this.FS_ACCURACY > 1000 && mtime % 2000 !== 0) this.FS_ACCURACY = 1000; } } diff --git a/lib/CaseSensitiveModulesWarning.js b/lib/CaseSensitiveModulesWarning.js index 132fcb714..30802331c 100644 --- a/lib/CaseSensitiveModulesWarning.js +++ b/lib/CaseSensitiveModulesWarning.js @@ -28,24 +28,26 @@ ${modulesList}`; a = a.identifier(); b = b.identifier(); /* istanbul ignore next */ - if(a < b) return -1; + if (a < b) return -1; /* istanbul ignore next */ - if(a > b) return 1; + if (a > b) return 1; /* istanbul ignore next */ return 0; }); } _moduleMessages(modules) { - return modules.map((m) => { - let message = `* ${m.identifier()}`; - const validReasons = m.reasons.filter((reason) => reason.module); + return modules + .map(m => { + let message = `* ${m.identifier()}`; + const validReasons = m.reasons.filter(reason => reason.module); - if(validReasons.length > 0) { - message += `\n Used by ${validReasons.length} module(s), i. e.`; - message += `\n ${validReasons[0].module.identifier()}`; - } - return message; - }).join("\n"); + if (validReasons.length > 0) { + message += `\n Used by ${validReasons.length} module(s), i. e.`; + message += `\n ${validReasons[0].module.identifier()}`; + } + return message; + }) + .join("\n"); } }; diff --git a/lib/Chunk.js b/lib/Chunk.js index b7086f3ff..529bc0471 100644 --- a/lib/Chunk.js +++ b/lib/Chunk.js @@ -9,24 +9,25 @@ const SortableSet = require("./util/SortableSet"); const GraphHelpers = require("./GraphHelpers"); let debugId = 1000; const ERR_CHUNK_ENTRY = "Chunk.entry was removed. Use hasRuntime()"; -const ERR_CHUNK_INITIAL = "Chunk.initial was removed. Use canBeInitial/isOnlyInitial()"; +const ERR_CHUNK_INITIAL = + "Chunk.initial was removed. Use canBeInitial/isOnlyInitial()"; const sortById = (a, b) => { - if(a.id < b.id) return -1; - if(b.id < a.id) return 1; + if (a.id < b.id) return -1; + if (b.id < a.id) return 1; return 0; }; const sortByIdentifier = (a, b) => { - if(a.identifier() > b.identifier()) return 1; - if(a.identifier() < b.identifier()) return -1; + if (a.identifier() > b.identifier()) return 1; + if (a.identifier() < b.identifier()) return -1; return 0; }; const getModulesIdent = set => { set.sort(); let str = ""; - for(const m of set) { + for (const m of set) { str += m.identifier() + "#"; } return str; @@ -36,14 +37,13 @@ const getArray = set => Array.from(set); const getModulesSize = set => { let count = 0; - for(const module of set) { + for (const module of set) { count += module.size(); } return count; }; class Chunk { - constructor(name) { this.id = null; this.ids = null; @@ -77,7 +77,7 @@ class Chunk { } hasRuntime() { - for(const chunkGroup of this._groups) { + for (const chunkGroup of this._groups) { // We only need to check the first one return chunkGroup.isInitial() && chunkGroup.getRuntimeChunk() === this; } @@ -85,18 +85,16 @@ class Chunk { } canBeInitial() { - for(const chunkGroup of this._groups) { - if(chunkGroup.isInitial()) - return true; + for (const chunkGroup of this._groups) { + if (chunkGroup.isInitial()) return true; } return false; } isOnlyInitial() { - if(this._groups.size <= 0) return false; - for(const chunkGroup of this._groups) { - if(!chunkGroup.isInitial()) - return false; + if (this._groups.size <= 0) return false; + for (const chunkGroup of this._groups) { + if (!chunkGroup.isInitial()) return false; } return true; } @@ -106,7 +104,7 @@ class Chunk { } addModule(module) { - if(!this._modules.has(module)) { + if (!this._modules.has(module)) { this._modules.add(module); return true; } @@ -114,7 +112,7 @@ class Chunk { } removeModule(module) { - if(this._modules.delete(module)) { + if (this._modules.delete(module)) { module.removeChunk(this); return true; } @@ -134,15 +132,13 @@ class Chunk { } addGroup(chunkGroup) { - if(this._groups.has(chunkGroup)) - return false; + if (this._groups.has(chunkGroup)) return false; this._groups.add(chunkGroup); return true; } removeGroup(chunkGroup) { - if(!this._groups.has(chunkGroup)) - return false; + if (!this._groups.has(chunkGroup)) return false; this._groups.delete(chunkGroup); return true; } @@ -162,18 +158,19 @@ class Chunk { compareTo(otherChunk) { this._modules.sort(); otherChunk._modules.sort(); - if(this._modules.size > otherChunk._modules.size) return -1; - if(this._modules.size < otherChunk._modules.size) return 1; + if (this._modules.size > otherChunk._modules.size) return -1; + if (this._modules.size < otherChunk._modules.size) return 1; const a = this._modules[Symbol.iterator](); const b = otherChunk._modules[Symbol.iterator](); - while(true) { // eslint-disable-line + while (true) { + // eslint-disable-line const aItem = a.next(); const bItem = b.next(); - if(aItem.done) return 0; + if (aItem.done) return 0; const aModuleIdentifier = aItem.value.identifier(); const bModuleIdentifier = bItem.value.identifier(); - if(aModuleIdentifier > bModuleIdentifier) return -1; - if(aModuleIdentifier < bModuleIdentifier) return 1; + if (aModuleIdentifier > bModuleIdentifier) return -1; + if (aModuleIdentifier < bModuleIdentifier) return 1; } } @@ -192,10 +189,10 @@ class Chunk { remove(reason) { // cleanup modules // Array.from is used here to create a clone, because removeChunk modifies this._modules - for(const module of Array.from(this._modules)) { + for (const module of Array.from(this._modules)) { module.removeChunk(this); } - for(const chunkGroup of this._groups) { + for (const chunkGroup of this._groups) { chunkGroup.removeChunk(this); } } @@ -207,25 +204,28 @@ class Chunk { } integrate(otherChunk, reason) { - if(!this.canBeIntegrated(otherChunk)) { + if (!this.canBeIntegrated(otherChunk)) { return false; } // Array.from is used here to create a clone, because moveModule modifies otherChunk._modules - for(const module of Array.from(otherChunk._modules)) { + for (const module of Array.from(otherChunk._modules)) { otherChunk.moveModule(module, this); } otherChunk._modules.clear(); - for(const chunkGroup of otherChunk._groups) { + for (const chunkGroup of otherChunk._groups) { chunkGroup.replaceChunk(otherChunk, this); this.addGroup(chunkGroup); } otherChunk._groups.clear(); - if(this.name && otherChunk.name) { - if(this.name.length !== otherChunk.name.length) - this.name = this.name.length < otherChunk.name.length ? this.name : otherChunk.name; + if (this.name && otherChunk.name) { + if (this.name.length !== otherChunk.name.length) + this.name = + this.name.length < otherChunk.name.length + ? this.name + : otherChunk.name; else this.name = this.name < otherChunk.name ? this.name : otherChunk.name; } @@ -234,7 +234,7 @@ class Chunk { } split(newChunk) { - for(const chunkGroup of this._groups) { + for (const chunkGroup of this._groups) { chunkGroup.insertChunk(newChunk, this); newChunk.addGroup(chunkGroup); } @@ -248,7 +248,7 @@ class Chunk { hash.update(`${this.id} `); hash.update(this.ids ? this.ids.join(",") : ""); hash.update(`${this.name || ""} `); - for(const m of this._modules) { + for (const m of this._modules) { hash.update(m.hash); } } @@ -256,31 +256,32 @@ class Chunk { canBeIntegrated(otherChunk) { const isAvailable = (a, b) => { const queue = new Set(b.groupsIterable); - for(const chunkGroup of queue) { - if(a.isInGroup(chunkGroup)) continue; - if(chunkGroup.isInitial()) return false; - for(const parent of chunkGroup.parentsIterable) - queue.add(parent); + for (const chunkGroup of queue) { + if (a.isInGroup(chunkGroup)) continue; + if (chunkGroup.isInitial()) return false; + for (const parent of chunkGroup.parentsIterable) queue.add(parent); } return true; }; - if(this.hasRuntime() !== otherChunk.hasRuntime()) { - if(this.hasRuntime()) { + if (this.hasRuntime() !== otherChunk.hasRuntime()) { + if (this.hasRuntime()) { return isAvailable(this, otherChunk); - } else if(otherChunk.hasRuntime()) { + } else if (otherChunk.hasRuntime()) { return isAvailable(otherChunk, this); } else { return false; } } - if(this.hasEntryModule() || otherChunk.hasEntryModule()) - return false; + if (this.hasEntryModule() || otherChunk.hasEntryModule()) return false; return true; } addMultiplierAndOverhead(size, options) { - const overhead = typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000; - const multiplicator = this.canBeInitial() ? (options.entryChunkMultiplicator || 10) : 1; + const overhead = + typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000; + const multiplicator = this.canBeInitial() + ? options.entryChunkMultiplicator || 10 + : 1; return size * multiplicator + overhead; } @@ -295,14 +296,14 @@ class Chunk { integratedSize(otherChunk, options) { // Chunk if it's possible to integrate this chunk - if(!this.canBeIntegrated(otherChunk)) { + if (!this.canBeIntegrated(otherChunk)) { return false; } let integratedModulesSize = this.modulesSize(); // only count modules that do not exist in this chunk! - for(const otherModule of otherChunk._modules) { - if(!this._modules.has(otherModule)) { + for (const otherModule of otherChunk._modules) { + if (!this._modules.has(otherModule)) { integratedModulesSize += otherModule.size(); } } @@ -323,18 +324,15 @@ class Chunk { const queue = new Set(this.groupsIterable); const chunks = new Set(); - for(const chunkGroup of queue) { - for(const chunk of chunkGroup.chunks) - initialChunks.add(chunk); + for (const chunkGroup of queue) { + for (const chunk of chunkGroup.chunks) initialChunks.add(chunk); } - for(const chunkGroup of queue) { - for(const chunk of chunkGroup.chunks) { - if(!initialChunks.has(chunk)) - chunks.add(chunk); + for (const chunkGroup of queue) { + for (const chunk of chunkGroup.chunks) { + if (!initialChunks.has(chunk)) chunks.add(chunk); } - for(const child of chunkGroup.childrenIterable) - queue.add(child); + for (const child of chunkGroup.childrenIterable) queue.add(child); } return chunks; @@ -344,10 +342,9 @@ class Chunk { const chunkHashMap = Object.create(null); const chunkNameMap = Object.create(null); - for(const chunk of this.getAllAsyncChunks()) { + for (const chunk of this.getAllAsyncChunks()) { chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash; - if(chunk.name) - chunkNameMap[chunk.id] = chunk.name; + if (chunk.name) chunkNameMap[chunk.id] = chunk.name; } return { @@ -360,11 +357,11 @@ class Chunk { const chunkModuleIdMap = Object.create(null); const chunkModuleHashMap = Object.create(null); - for(const chunk of this.getAllAsyncChunks()) { + for (const chunk of this.getAllAsyncChunks()) { let array; - for(const module of chunk.modulesIterable) { - if(filterFn(module)) { - if(array === undefined) { + for (const module of chunk.modulesIterable) { + if (filterFn(module)) { + if (array === undefined) { array = []; chunkModuleIdMap[chunk.id] = array; } @@ -372,7 +369,7 @@ class Chunk { chunkModuleHashMap[module.id] = module.renderedHash; } } - if(array !== undefined) { + if (array !== undefined) { array.sort(); } } @@ -387,19 +384,17 @@ class Chunk { const queue = new Set(this.groupsIterable); const chunksProcessed = new Set(); - for(const chunkGroup of queue) { - for(const chunk of chunkGroup.chunks) { - if(!chunksProcessed.has(chunk)) { + for (const chunkGroup of queue) { + for (const chunk of chunkGroup.chunks) { + if (!chunksProcessed.has(chunk)) { chunksProcessed.add(chunk); - if(!filterChunkFn || filterChunkFn(chunk)) { - for(const module of chunk.modulesIterable) - if(filterFn(module)) - return true; + if (!filterChunkFn || filterChunkFn(chunk)) { + for (const module of chunk.modulesIterable) + if (filterFn(module)) return true; } } } - for(const child of chunkGroup.childrenIterable) - queue.add(child); + for (const child of chunkGroup.childrenIterable) queue.add(child); } return false; } @@ -462,7 +457,9 @@ Object.defineProperty(Chunk.prototype, "blocks", { Object.defineProperty(Chunk.prototype, "entrypoints", { configurable: false, get() { - throw new Error("Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead"); + throw new Error( + "Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead" + ); }, set() { throw new Error("Chunk.entrypoints: Use Chunks.addGroup instead"); diff --git a/lib/ChunkGroup.js b/lib/ChunkGroup.js index caa5a9a92..7f765ade3 100644 --- a/lib/ChunkGroup.js +++ b/lib/ChunkGroup.js @@ -12,16 +12,16 @@ let debugId = 5000; const getArray = set => Array.from(set); const sortById = (a, b) => { - if(a.id < b.id) return -1; - if(b.id < a.id) return 1; + if (a.id < b.id) return -1; + if (b.id < a.id) return 1; return 0; }; const sortOrigin = (a, b) => { const aIdent = a.module ? a.module.identifier() : ""; const bIdent = b.module ? b.module.identifier() : ""; - if(aIdent < bIdent) return -1; - if(aIdent > bIdent) return 1; + if (aIdent < bIdent) return -1; + if (aIdent > bIdent) return 1; return compareLocations(a.loc, b.loc); }; @@ -47,10 +47,10 @@ class ChunkGroup { unshiftChunk(chunk) { const oldIdx = this.chunks.indexOf(chunk); - if(oldIdx > 0) { + if (oldIdx > 0) { this.chunks.splice(oldIdx, 1); this.chunks.unshift(chunk); - } else if(oldIdx < 0) { + } else if (oldIdx < 0) { this.chunks.unshift(chunk); return true; } @@ -60,13 +60,13 @@ class ChunkGroup { insertChunk(chunk, before) { const oldIdx = this.chunks.indexOf(chunk); const idx = this.chunks.indexOf(before); - if(idx < 0) { + if (idx < 0) { throw new Error("before chunk not found"); } - if(oldIdx >= 0 && oldIdx > idx) { + if (oldIdx >= 0 && oldIdx > idx) { this.chunks.splice(oldIdx, 1); this.chunks.splice(idx, 0, chunk); - } else if(oldIdx < 0) { + } else if (oldIdx < 0) { this.chunks.splice(idx, 0, chunk); return true; } @@ -75,7 +75,7 @@ class ChunkGroup { pushChunk(chunk) { const oldIdx = this.chunks.indexOf(chunk); - if(oldIdx >= 0) { + if (oldIdx >= 0) { return false; } this.chunks.push(chunk); @@ -84,16 +84,16 @@ class ChunkGroup { replaceChunk(oldChunk, newChunk) { const oldIdx = this.chunks.indexOf(oldChunk); - if(oldIdx < 0) return false; + if (oldIdx < 0) return false; const newIdx = this.chunks.indexOf(newChunk); - if(newIdx < 0) { + if (newIdx < 0) { this.chunks[oldIdx] = newChunk; return true; } - if(newIdx < oldIdx) { + if (newIdx < oldIdx) { this.chunks.splice(oldIdx, 1); return true; - } else if(newIdx !== oldIdx) { + } else if (newIdx !== oldIdx) { this.chunks[oldIdx] = newChunk; this.chunks.splice(newIdx, 1); return true; @@ -102,7 +102,7 @@ class ChunkGroup { removeChunk(chunk) { const idx = this.chunks.indexOf(chunk); - if(idx >= 0) { + if (idx >= 0) { this.chunks.splice(idx, 1); return true; } @@ -114,7 +114,7 @@ class ChunkGroup { } addChild(chunk) { - if(this._children.has(chunk)) { + if (this._children.has(chunk)) { return false; } this._children.add(chunk); @@ -134,7 +134,7 @@ class ChunkGroup { } removeChild(chunk) { - if(!this._children.has(chunk)) { + if (!this._children.has(chunk)) { return false; } @@ -144,7 +144,7 @@ class ChunkGroup { } addParent(parentChunk) { - if(!this._parents.has(parentChunk)) { + if (!this._parents.has(parentChunk)) { this._parents.add(parentChunk); return true; } @@ -157,8 +157,7 @@ class ChunkGroup { setParents(newParents) { this._parents.clear(); - for(const p of newParents) - this._parents.add(p); + for (const p of newParents) this._parents.add(p); } getNumberOfParents() { @@ -174,7 +173,7 @@ class ChunkGroup { } removeParent(chunk) { - if(this._parents.delete(chunk)) { + if (this._parents.delete(chunk)) { chunk.removeChunk(this); return true; } @@ -201,7 +200,7 @@ class ChunkGroup { } addBlock(block) { - if(!this._blocks.has(block)) { + if (!this._blocks.has(block)) { this._blocks.add(block); return true; } @@ -217,21 +216,20 @@ class ChunkGroup { } containsModule(module) { - for(const chunk of this.chunks) { - if(chunk.containsModule(module)) - return true; + for (const chunk of this.chunks) { + if (chunk.containsModule(module)) return true; } return false; } remove(reason) { // cleanup parents - for(const parentChunkGroup of this._parents) { + for (const parentChunkGroup of this._parents) { // remove this chunk from its parents parentChunkGroup._children.delete(this); // cleanup "sub chunks" - for(const chunkGroup of this._children) { + for (const chunkGroup of this._children) { /** * remove this chunk as "intermediary" and connect * it "sub chunks" and parents directly @@ -249,18 +247,18 @@ class ChunkGroup { * This can not be done in the above loop * as it is not garuanteed that `this._parents` contains anything. */ - for(const chunkGroup of this._children) { + for (const chunkGroup of this._children) { // remove this as parent of every "sub chunk" chunkGroup._parents.delete(this); } // cleanup blocks - for(const block of this._blocks) { + for (const block of this._blocks) { block.chunkGroup = null; } // remove chunks - for(const chunk of this.chunks) { + for (const chunk of this.chunks) { chunk.removeGroup(this); } } @@ -273,13 +271,21 @@ class ChunkGroup { checkConstraints() { const chunk = this; - for(const child of chunk._children) { - if(!child._parents.has(chunk)) - throw new Error(`checkConstraints: child missing parent ${chunk.debugId} -> ${child.debugId}`); + for (const child of chunk._children) { + if (!child._parents.has(chunk)) + throw new Error( + `checkConstraints: child missing parent ${chunk.debugId} -> ${ + child.debugId + }` + ); } - for(const parentChunk of chunk._parents) { - if(!parentChunk._children.has(chunk)) - throw new Error(`checkConstraints: parent missing child ${parentChunk.debugId} <- ${chunk.debugId}`); + for (const parentChunk of chunk._parents) { + if (!parentChunk._children.has(chunk)) + throw new Error( + `checkConstraints: parent missing child ${parentChunk.debugId} <- ${ + chunk.debugId + }` + ); } } } diff --git a/lib/ChunkTemplate.js b/lib/ChunkTemplate.js index 087801e19..13f554b13 100644 --- a/lib/ChunkTemplate.js +++ b/lib/ChunkTemplate.js @@ -14,11 +14,21 @@ module.exports = class ChunkTemplate extends Tapable { this.outputOptions = outputOptions || {}; this.hooks = { renderManifest: new SyncWaterfallHook(["result", "options"]), - modules: new SyncWaterfallHook(["source", "chunk", "moduleTemplate", "dependencyTemplates"]), - render: new SyncWaterfallHook(["source", "chunk", "moduleTemplate", "dependencyTemplates"]), + modules: new SyncWaterfallHook([ + "source", + "chunk", + "moduleTemplate", + "dependencyTemplates" + ]), + render: new SyncWaterfallHook([ + "source", + "chunk", + "moduleTemplate", + "dependencyTemplates" + ]), renderWithEntry: new SyncWaterfallHook(["source", "chunk"]), hash: new SyncHook(["hash"]), - hashForChunk: new SyncHook(["hash", "chunk"]), + hashForChunk: new SyncHook(["hash", "chunk"]) }; } diff --git a/lib/CompatibilityPlugin.js b/lib/CompatibilityPlugin.js index 25a4a8e7f..bb92d2f92 100644 --- a/lib/CompatibilityPlugin.js +++ b/lib/CompatibilityPlugin.js @@ -9,37 +9,55 @@ const ConstDependency = require("./dependencies/ConstDependency"); const NullFactory = require("./NullFactory"); class CompatibilityPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("CompatibilityPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compiler.hooks.compilation.tap( + "CompatibilityPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - normalModuleFactory.hooks.parser.for("javascript/auto").tap("CompatibilityPlugin", (parser, parserOptions) => { + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("CompatibilityPlugin", (parser, parserOptions) => { + if ( + typeof parserOptions.browserify !== "undefined" && + !parserOptions.browserify + ) + return; - if(typeof parserOptions.browserify !== "undefined" && !parserOptions.browserify) - return; - - parser.hooks.call.for("require").tap("CompatibilityPlugin", (expr) => { - // support for browserify style require delegator: "require(o, !0)" - if(expr.arguments.length !== 2) return; - const second = parser.evaluateExpression(expr.arguments[1]); - if(!second.isBoolean()) return; - if(second.asBool() !== true) return; - const dep = new ConstDependency("require", expr.callee.range); - dep.loc = expr.loc; - if(parser.state.current.dependencies.length > 1) { - const last = parser.state.current.dependencies[parser.state.current.dependencies.length - 1]; - if(last.critical && last.options && last.options.request === "." && last.userRequest === "." && last.options.recursive) - parser.state.current.dependencies.pop(); - } - parser.state.current.addDependency(dep); - return true; - }); - }); - }); + parser.hooks.call + .for("require") + .tap("CompatibilityPlugin", expr => { + // support for browserify style require delegator: "require(o, !0)" + if (expr.arguments.length !== 2) return; + const second = parser.evaluateExpression(expr.arguments[1]); + if (!second.isBoolean()) return; + if (second.asBool() !== true) return; + const dep = new ConstDependency("require", expr.callee.range); + dep.loc = expr.loc; + if (parser.state.current.dependencies.length > 1) { + const last = + parser.state.current.dependencies[ + parser.state.current.dependencies.length - 1 + ]; + if ( + last.critical && + last.options && + last.options.request === "." && + last.userRequest === "." && + last.options.recursive + ) + parser.state.current.dependencies.pop(); + } + parser.state.current.addDependency(dep); + return true; + }); + }); + } + ); } } module.exports = CompatibilityPlugin; diff --git a/lib/Compilation.js b/lib/Compilation.js index c3e34ba70..ff7470869 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -35,48 +35,52 @@ const SortableSet = require("./util/SortableSet"); const GraphHelpers = require("./GraphHelpers"); const byId = (a, b) => { - if(a.id < b.id) return -1; - if(a.id > b.id) return 1; + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; return 0; }; const byIdOrIdentifier = (a, b) => { - if(a.id < b.id) return -1; - if(a.id > b.id) return 1; + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; const identA = a.identifier(); const identB = b.identifier(); - if(identA < identB) return -1; - if(identA > identB) return 1; + if (identA < identB) return -1; + if (identA > identB) return 1; return 0; }; const byIndexOrIdentifier = (a, b) => { - if(a.index < b.index) return -1; - if(a.index > b.index) return 1; + if (a.index < b.index) return -1; + if (a.index > b.index) return 1; const identA = a.identifier(); const identB = b.identifier(); - if(identA < identB) return -1; - if(identA > identB) return 1; + if (identA < identB) return -1; + if (identA > identB) return 1; return 0; }; const iterationBlockVariable = (variables, fn) => { - for(let indexVariable = 0; indexVariable < variables.length; indexVariable++) { + for ( + let indexVariable = 0; + indexVariable < variables.length; + indexVariable++ + ) { const varDep = variables[indexVariable].dependencies; - for(let indexVDep = 0; indexVDep < varDep.length; indexVDep++) { + for (let indexVDep = 0; indexVDep < varDep.length; indexVDep++) { fn(varDep[indexVDep]); } } }; const iterationOfArrayCallback = (arr, fn) => { - for(let index = 0; index < arr.length; index++) { + for (let index = 0; index < arr.length; index++) { fn(arr[index]); } }; function addAllToSet(set, otherSet) { - for(const item of otherSet) { + for (const item of otherSet) { set.add(item); } } @@ -169,7 +173,11 @@ class Compilation extends Tapable { assetPath: new SyncWaterfallHook(["filename", "data"]), // TODO MainTemplate needAdditionalPass: new SyncBailHook([]), - childCompiler: new SyncHook(["childCompiler", "compilerName", "compilerIndex"]), + childCompiler: new SyncHook([ + "childCompiler", + "compilerName", + "compilerIndex" + ]), // TODO the following hooks are weirdly located here // TODO move them for webpack 5 @@ -178,10 +186,10 @@ class Compilation extends Tapable { optimizeExtractedChunksBasic: new SyncBailHook(["chunks"]), optimizeExtractedChunks: new SyncBailHook(["chunks"]), optimizeExtractedChunksAdvanced: new SyncBailHook(["chunks"]), - afterOptimizeExtractedChunks: new SyncHook(["chunks"]), + afterOptimizeExtractedChunks: new SyncHook(["chunks"]) }; this._pluginCompat.tap("Compilation", options => { - switch(options.name) { + switch (options.name) { case "optimize-tree": case "additional-assets": case "optimize-chunk-assets": @@ -196,7 +204,7 @@ class Compilation extends Tapable { this.inputFileSystem = compiler.inputFileSystem; this.requestShortener = compiler.requestShortener; - const options = this.options = compiler.options; + const options = (this.options = compiler.options); this.outputOptions = options && options.output; this.bail = options && options.bail; this.profile = options && options.profile; @@ -204,8 +212,13 @@ class Compilation extends Tapable { this.mainTemplate = new MainTemplate(this.outputOptions); this.chunkTemplate = new ChunkTemplate(this.outputOptions); - this.hotUpdateChunkTemplate = new HotUpdateChunkTemplate(this.outputOptions); - this.runtimeTemplate = new RuntimeTemplate(this.outputOptions, this.requestShortener); + this.hotUpdateChunkTemplate = new HotUpdateChunkTemplate( + this.outputOptions + ); + this.runtimeTemplate = new RuntimeTemplate( + this.outputOptions, + this.requestShortener + ); this.moduleTemplates = { javascript: new ModuleTemplate(this.runtimeTemplate), webassembly: new ModuleTemplate(this.runtimeTemplate) @@ -249,7 +262,7 @@ class Compilation extends Tapable { addModule(module, cacheGroup) { const identifier = module.identifier(); const alreadyAddedModule = this._modules.get(identifier); - if(alreadyAddedModule) { + if (alreadyAddedModule) { return { module: alreadyAddedModule, issuer: false, @@ -258,20 +271,23 @@ class Compilation extends Tapable { }; } const cacheName = (cacheGroup || "m") + identifier; - if(this.cache && this.cache[cacheName]) { + if (this.cache && this.cache[cacheName]) { const cacheModule = this.cache[cacheName]; let rebuild = true; - if(this.fileTimestamps && this.contextTimestamps) { - rebuild = cacheModule.needRebuild(this.fileTimestamps, this.contextTimestamps); + if (this.fileTimestamps && this.contextTimestamps) { + rebuild = cacheModule.needRebuild( + this.fileTimestamps, + this.contextTimestamps + ); } - if(!rebuild) { + if (!rebuild) { cacheModule.disconnect(); this._modules.set(identifier, cacheModule); this.modules.push(cacheModule); - for(const err of cacheModule.errors) this.errors.push(err); - for(const err of cacheModule.warnings) this.warnings.push(err); + for (const err of cacheModule.errors) this.errors.push(err); + for (const err of cacheModule.warnings) this.warnings.push(err); return { module: cacheModule, issuer: true, @@ -283,7 +299,7 @@ class Compilation extends Tapable { module = cacheModule; } this._modules.set(identifier, module); - if(this.cache) { + if (this.cache) { this.cache[cacheName] = module; } this.modules.push(module); @@ -306,7 +322,7 @@ class Compilation extends Tapable { waitForBuildingFinished(module, callback) { let callbackList = this._buildingModules.get(module); - if(callbackList) { + if (callbackList) { callbackList.push(() => callback()); } else { process.nextTick(callback); @@ -315,45 +331,53 @@ class Compilation extends Tapable { buildModule(module, optional, origin, dependencies, thisCallback) { let callbackList = this._buildingModules.get(module); - if(callbackList) { + if (callbackList) { callbackList.push(thisCallback); return; } - this._buildingModules.set(module, callbackList = [thisCallback]); + this._buildingModules.set(module, (callbackList = [thisCallback])); const callback = err => { this._buildingModules.delete(module); - for(const cb of callbackList) cb(err); + for (const cb of callbackList) cb(err); }; this.hooks.buildModule.call(module); - module.build(this.options, this, this.resolverFactory.get("normal", module.resolveOptions), this.inputFileSystem, (error) => { - const errors = module.errors; - for(let indexError = 0; indexError < errors.length; indexError++) { - const err = errors[indexError]; - err.origin = origin; - err.dependencies = dependencies; - if(optional) - this.warnings.push(err); - else - this.errors.push(err); - } + module.build( + this.options, + this, + this.resolverFactory.get("normal", module.resolveOptions), + this.inputFileSystem, + error => { + const errors = module.errors; + for (let indexError = 0; indexError < errors.length; indexError++) { + const err = errors[indexError]; + err.origin = origin; + err.dependencies = dependencies; + if (optional) this.warnings.push(err); + else this.errors.push(err); + } - const warnings = module.warnings; - for(let indexWarning = 0; indexWarning < warnings.length; indexWarning++) { - const war = warnings[indexWarning]; - war.origin = origin; - war.dependencies = dependencies; - this.warnings.push(war); + const warnings = module.warnings; + for ( + let indexWarning = 0; + indexWarning < warnings.length; + indexWarning++ + ) { + const war = warnings[indexWarning]; + war.origin = origin; + war.dependencies = dependencies; + this.warnings.push(war); + } + module.dependencies.sort(Dependency.compare); + if (error) { + this.hooks.failedModule.call(module, error); + return callback(error); + } + this.hooks.succeedModule.call(module); + return callback(); } - module.dependencies.sort(Dependency.compare); - if(error) { - this.hooks.failedModule.call(module, error); - return callback(error); - } - this.hooks.succeedModule.call(module); - return callback(); - }); + ); } processModuleDependencies(module, callback) { @@ -361,42 +385,45 @@ class Compilation extends Tapable { const addDependency = dep => { const resourceIdent = dep.getResourceIdentifier(); - if(resourceIdent) { + if (resourceIdent) { const factory = this.dependencyFactories.get(dep.constructor); - if(factory === undefined) - throw new Error(`No module factory available for dependency type: ${dep.constructor.name}`); + if (factory === undefined) + throw new Error( + `No module factory available for dependency type: ${ + dep.constructor.name + }` + ); let innerMap = dependencies.get(factory); - if(innerMap === undefined) - dependencies.set(factory, innerMap = new Map()); + if (innerMap === undefined) + dependencies.set(factory, (innerMap = new Map())); let list = innerMap.get(resourceIdent); - if(list === undefined) - innerMap.set(resourceIdent, list = []); + if (list === undefined) innerMap.set(resourceIdent, (list = [])); list.push(dep); } }; const addDependenciesBlock = block => { - if(block.dependencies) { + if (block.dependencies) { iterationOfArrayCallback(block.dependencies, addDependency); } - if(block.blocks) { + if (block.blocks) { iterationOfArrayCallback(block.blocks, addDependenciesBlock); } - if(block.variables) { + if (block.variables) { iterationBlockVariable(block.variables, addDependency); } }; try { addDependenciesBlock(module); - } catch(e) { + } catch (e) { callback(e); } const sortedDependencies = []; - for(const pair1 of dependencies) { - for(const pair2 of pair1[1]) { + for (const pair1 of dependencies) { + for (const pair2 of pair1[1]) { sortedDependencies.push({ factory: pair1[0], dependencies: pair2[1] @@ -404,246 +431,294 @@ class Compilation extends Tapable { } } - this.addModuleDependencies(module, sortedDependencies, this.bail, null, true, callback); + this.addModuleDependencies( + module, + sortedDependencies, + this.bail, + null, + true, + callback + ); } - addModuleDependencies(module, dependencies, bail, cacheGroup, recursive, callback) { + addModuleDependencies( + module, + dependencies, + bail, + cacheGroup, + recursive, + callback + ) { let _this = this; const start = _this.profile && Date.now(); const currentProfile = _this.profile && {}; - asyncLib.forEach(dependencies, (item, callback) => { - const dependencies = item.dependencies; + asyncLib.forEach( + dependencies, + (item, callback) => { + const dependencies = item.dependencies; - const errorAndCallback = err => { - err.origin = module; - _this.errors.push(err); - if(bail) { - callback(err); - } else { - callback(); - } - }; - const warningAndCallback = err => { - err.origin = module; - _this.warnings.push(err); - callback(); - }; - - const semaphore = _this.semaphore; - semaphore.acquire(() => { - if(_this === null) return semaphore.release(); - - const factory = item.factory; - factory.create({ - contextInfo: { - issuer: module.nameForCondition && module.nameForCondition(), - compiler: _this.compiler.name - }, - resolveOptions: module.resolveOptions, - context: module.context, - dependencies: dependencies - }, (err, dependentModule) => { - if(_this === null) return semaphore.release(); - - let afterFactory; - - const isOptional = () => { - return dependencies.every(d => d.optional); - }; - - const errorOrWarningAndCallback = err => { - if(isOptional()) { - return warningAndCallback(err); - } else { - return errorAndCallback(err); - } - }; - - if(err) { - semaphore.release(); - return errorOrWarningAndCallback(new ModuleNotFoundError(module, err, dependencies)); - } - if(!dependentModule) { - semaphore.release(); - return process.nextTick(callback); - } - if(currentProfile) { - afterFactory = Date.now(); - currentProfile.factory = afterFactory - start; - } - - const iterationDependencies = depend => { - for(let index = 0; index < depend.length; index++) { - const dep = depend[index]; - dep.module = dependentModule; - dependentModule.addReason(module, dep); - } - }; - - const addModuleResult = _this.addModule(dependentModule, cacheGroup); - dependentModule = addModuleResult.module; - iterationDependencies(dependencies); - - const afterBuild = () => { - if(currentProfile) { - const afterBuilding = Date.now(); - currentProfile.building = afterBuilding - afterFactory; - } - - if(recursive && addModuleResult.dependencies) { - _this.processModuleDependencies(dependentModule, callback); - } else { - return callback(); - } - }; - - if(addModuleResult.issuer) { - if(currentProfile) { - dependentModule.profile = currentProfile; - } - - dependentModule.issuer = module; + const errorAndCallback = err => { + err.origin = module; + _this.errors.push(err); + if (bail) { + callback(err); } else { - if(_this.profile) { - if(module.profile) { - const time = Date.now() - start; - if(!module.profile.dependencies || time > module.profile.dependencies) { - module.profile.dependencies = time; + callback(); + } + }; + const warningAndCallback = err => { + err.origin = module; + _this.warnings.push(err); + callback(); + }; + + const semaphore = _this.semaphore; + semaphore.acquire(() => { + if (_this === null) return semaphore.release(); + + const factory = item.factory; + factory.create( + { + contextInfo: { + issuer: module.nameForCondition && module.nameForCondition(), + compiler: _this.compiler.name + }, + resolveOptions: module.resolveOptions, + context: module.context, + dependencies: dependencies + }, + (err, dependentModule) => { + if (_this === null) return semaphore.release(); + + let afterFactory; + + const isOptional = () => { + return dependencies.every(d => d.optional); + }; + + const errorOrWarningAndCallback = err => { + if (isOptional()) { + return warningAndCallback(err); + } else { + return errorAndCallback(err); + } + }; + + if (err) { + semaphore.release(); + return errorOrWarningAndCallback( + new ModuleNotFoundError(module, err, dependencies) + ); + } + if (!dependentModule) { + semaphore.release(); + return process.nextTick(callback); + } + if (currentProfile) { + afterFactory = Date.now(); + currentProfile.factory = afterFactory - start; + } + + const iterationDependencies = depend => { + for (let index = 0; index < depend.length; index++) { + const dep = depend[index]; + dep.module = dependentModule; + dependentModule.addReason(module, dep); + } + }; + + const addModuleResult = _this.addModule( + dependentModule, + cacheGroup + ); + dependentModule = addModuleResult.module; + iterationDependencies(dependencies); + + const afterBuild = () => { + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + if (recursive && addModuleResult.dependencies) { + _this.processModuleDependencies(dependentModule, callback); + } else { + return callback(); + } + }; + + if (addModuleResult.issuer) { + if (currentProfile) { + dependentModule.profile = currentProfile; + } + + dependentModule.issuer = module; + } else { + if (_this.profile) { + if (module.profile) { + const time = Date.now() - start; + if ( + !module.profile.dependencies || + time > module.profile.dependencies + ) { + module.profile.dependencies = time; + } + } } } - } - } - if(addModuleResult.build) { - _this.buildModule(dependentModule, isOptional(), module, dependencies, err => { - if(_this === null) return semaphore.release(); + if (addModuleResult.build) { + _this.buildModule( + dependentModule, + isOptional(), + module, + dependencies, + err => { + if (_this === null) return semaphore.release(); - if(err) { + if (err) { + semaphore.release(); + return errorOrWarningAndCallback(err); + } + + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + semaphore.release(); + afterBuild(); + } + ); + } else { semaphore.release(); - return errorOrWarningAndCallback(err); + _this.waitForBuildingFinished(dependentModule, afterBuild); } - - if(currentProfile) { - const afterBuilding = Date.now(); - currentProfile.building = afterBuilding - afterFactory; - } - - semaphore.release(); - afterBuild(); - }); - } else { - semaphore.release(); - _this.waitForBuildingFinished(dependentModule, afterBuild); - } + } + ); }); - }); - }, err => { - // In V8, the Error objects keep a reference to the functions on the stack. These warnings & - // errors are created inside closures that keep a reference to the Compilation, so errors are - // leaking the Compilation object. + }, + err => { + // In V8, the Error objects keep a reference to the functions on the stack. These warnings & + // errors are created inside closures that keep a reference to the Compilation, so errors are + // leaking the Compilation object. - if(err) { - err.stack = err.stack; - return callback(err); + if (err) { + err.stack = err.stack; + return callback(err); + } + + return process.nextTick(callback); } - - return process.nextTick(callback); - }); + ); } _addModuleChain(context, dependency, onModule, callback) { const start = this.profile && Date.now(); const currentProfile = this.profile && {}; - const errorAndCallback = this.bail ? (err) => { - callback(err); - } : (err) => { - err.dependencies = [dependency]; - this.errors.push(err); - callback(); - }; + const errorAndCallback = this.bail + ? err => { + callback(err); + } + : err => { + err.dependencies = [dependency]; + this.errors.push(err); + callback(); + }; - if(typeof dependency !== "object" || dependency === null || !dependency.constructor) { + if ( + typeof dependency !== "object" || + dependency === null || + !dependency.constructor + ) { throw new Error("Parameter 'dependency' must be a Dependency"); } const moduleFactory = this.dependencyFactories.get(dependency.constructor); - if(!moduleFactory) { - throw new Error(`No dependency factory available for this dependency type: ${dependency.constructor.name}`); + if (!moduleFactory) { + throw new Error( + `No dependency factory available for this dependency type: ${ + dependency.constructor.name + }` + ); } this.semaphore.acquire(() => { - moduleFactory.create({ - contextInfo: { - issuer: "", - compiler: this.compiler.name + moduleFactory.create( + { + contextInfo: { + issuer: "", + compiler: this.compiler.name + }, + context: context, + dependencies: [dependency] }, - context: context, - dependencies: [dependency] - }, (err, module) => { - if(err) { - this.semaphore.release(); - return errorAndCallback(new EntryModuleNotFoundError(err)); - } - - let afterFactory; - - if(currentProfile) { - afterFactory = Date.now(); - currentProfile.factory = afterFactory - start; - } - - const addModuleResult = this.addModule(module); - module = addModuleResult.module; - - onModule(module); - - dependency.module = module; - module.addReason(null, dependency); - - const afterBuild = () => { - if(currentProfile) { - const afterBuilding = Date.now(); - currentProfile.building = afterBuilding - afterFactory; + (err, module) => { + if (err) { + this.semaphore.release(); + return errorAndCallback(new EntryModuleNotFoundError(err)); } - if(addModuleResult.dependencies) { - this.processModuleDependencies(module, err => { - if(err) return callback(err); - callback(null, module); - }); - } else { - return callback(null, module); + let afterFactory; + + if (currentProfile) { + afterFactory = Date.now(); + currentProfile.factory = afterFactory - start; } - }; - if(addModuleResult.issuer) { - if(currentProfile) { - module.profile = currentProfile; - } - } + const addModuleResult = this.addModule(module); + module = addModuleResult.module; - if(addModuleResult.build) { - this.buildModule(module, false, null, null, err => { - if(err) { - this.semaphore.release(); - return errorAndCallback(err); - } + onModule(module); - if(currentProfile) { + dependency.module = module; + module.addReason(null, dependency); + + const afterBuild = () => { + if (currentProfile) { const afterBuilding = Date.now(); currentProfile.building = afterBuilding - afterFactory; } + if (addModuleResult.dependencies) { + this.processModuleDependencies(module, err => { + if (err) return callback(err); + callback(null, module); + }); + } else { + return callback(null, module); + } + }; + + if (addModuleResult.issuer) { + if (currentProfile) { + module.profile = currentProfile; + } + } + + if (addModuleResult.build) { + this.buildModule(module, false, null, null, err => { + if (err) { + this.semaphore.release(); + return errorAndCallback(err); + } + + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + this.semaphore.release(); + afterBuild(); + }); + } else { this.semaphore.release(); - afterBuild(); - }); - } else { - this.semaphore.release(); - this.waitForBuildingFinished(module, afterBuild); + this.waitForBuildingFinished(module, afterBuild); + } } - }); + ); }); } @@ -654,44 +729,50 @@ class Compilation extends Tapable { module: null }; this._preparedEntrypoints.push(slot); - this._addModuleChain(context, entry, (module) => { + this._addModuleChain( + context, + entry, + module => { + this.entries.push(module); + }, + (err, module) => { + if (err) { + return callback(err); + } - this.entries.push(module); - - }, (err, module) => { - if(err) { - return callback(err); + if (module) { + slot.module = module; + } else { + const idx = this._preparedEntrypoints.indexOf(slot); + this._preparedEntrypoints.splice(idx, 1); + } + return callback(null, module); } - - if(module) { - slot.module = module; - } else { - const idx = this._preparedEntrypoints.indexOf(slot); - this._preparedEntrypoints.splice(idx, 1); - } - return callback(null, module); - }); + ); } prefetch(context, dependency, callback) { - this._addModuleChain(context, dependency, module => { - - module.prefetched = true; - - }, callback); + this._addModuleChain( + context, + dependency, + module => { + module.prefetched = true; + }, + callback + ); } rebuildModule(module, thisCallback) { let callbackList = this._rebuildingModules.get(module); - if(callbackList) { + if (callbackList) { callbackList.push(thisCallback); return; } - this._rebuildingModules.set(module, callbackList = [thisCallback]); + this._rebuildingModules.set(module, (callbackList = [thisCallback])); const callback = err => { this._rebuildingModules.delete(module); - for(const cb of callbackList) cb(err); + for (const cb of callbackList) cb(err); }; this.hooks.rebuildModule.call(module); @@ -699,14 +780,14 @@ class Compilation extends Tapable { const oldVariables = module.variables.slice(); const oldBlocks = module.blocks.slice(); module.unbuild(); - this.buildModule(module, false, module, null, (err) => { - if(err) { + this.buildModule(module, false, module, null, err => { + if (err) { this.hooks.finishRebuildingModule.call(module); return callback(err); } - this.processModuleDependencies(module, (err) => { - if(err) return callback(err); + this.processModuleDependencies(module, err => { + if (err) return callback(err); this.removeReasonsOfDependencyBlock(module, { dependencies: oldDependencies, variables: oldVariables, @@ -715,7 +796,6 @@ class Compilation extends Tapable { this.hooks.finishRebuildingModule.call(module); callback(); }); - }); } @@ -723,7 +803,7 @@ class Compilation extends Tapable { const modules = this.modules; this.hooks.finishModules.call(modules); - for(let index = 0; index < modules.length; index++) { + for (let index = 0; index < modules.length; index++) { const module = modules[index]; this.reportDependencyErrorsAndWarnings(module, [module]); } @@ -737,7 +817,7 @@ class Compilation extends Tapable { this.namedChunkGroups.clear(); this.additionalChunkAssets.length = 0; this.assets = {}; - for(const module of this.modules) { + for (const module of this.modules) { module.unseal(); } } @@ -745,14 +825,18 @@ class Compilation extends Tapable { seal(callback) { this.hooks.seal.call(); - while(this.hooks.optimizeDependenciesBasic.call(this.modules) || + while ( + this.hooks.optimizeDependenciesBasic.call(this.modules) || this.hooks.optimizeDependencies.call(this.modules) || - this.hooks.optimizeDependenciesAdvanced.call(this.modules)) { /* empty */ } + this.hooks.optimizeDependenciesAdvanced.call(this.modules) + ) { + /* empty */ + } this.hooks.afterOptimizeDependencies.call(this.modules); this.nextFreeModuleIndex = 0; this.nextFreeModuleIndex2 = 0; - for(const preparedEntrypoint of this._preparedEntrypoints) { + for (const preparedEntrypoint of this._preparedEntrypoints) { const module = preparedEntrypoint.module; const name = preparedEntrypoint.name; const chunk = this.addChunk(name); @@ -776,26 +860,38 @@ class Compilation extends Tapable { this.sortModules(this.modules); this.hooks.optimize.call(); - while(this.hooks.optimizeModulesBasic.call(this.modules) || + while ( + this.hooks.optimizeModulesBasic.call(this.modules) || this.hooks.optimizeModules.call(this.modules) || - this.hooks.optimizeModulesAdvanced.call(this.modules)) { /* empty */ } + this.hooks.optimizeModulesAdvanced.call(this.modules) + ) { + /* empty */ + } this.hooks.afterOptimizeModules.call(this.modules); - while(this.hooks.optimizeChunksBasic.call(this.chunks, this.chunkGroups) || + while ( + this.hooks.optimizeChunksBasic.call(this.chunks, this.chunkGroups) || this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups) || - this.hooks.optimizeChunksAdvanced.call(this.chunks, this.chunkGroups)) { /* empty */ } + this.hooks.optimizeChunksAdvanced.call(this.chunks, this.chunkGroups) + ) { + /* empty */ + } this.hooks.afterOptimizeChunks.call(this.chunks, this.chunkGroups); this.hooks.optimizeTree.callAsync(this.chunks, this.modules, err => { - if(err) { + if (err) { return callback(err); } this.hooks.afterOptimizeTree.call(this.chunks, this.modules); - while(this.hooks.optimizeChunkModulesBasic.call(this.chunks, this.modules) || + while ( + this.hooks.optimizeChunkModulesBasic.call(this.chunks, this.modules) || this.hooks.optimizeChunkModules.call(this.chunks, this.modules) || - this.hooks.optimizeChunkModulesAdvanced.call(this.chunks, this.modules)) { /* empty */ } + this.hooks.optimizeChunkModulesAdvanced.call(this.chunks, this.modules) + ) { + /* empty */ + } this.hooks.afterOptimizeChunkModules.call(this.chunks, this.modules); const shouldRecord = this.hooks.shouldRecord.call() !== false; @@ -820,44 +916,41 @@ class Compilation extends Tapable { this.sortItemsWithChunkIds(); - if(shouldRecord) + if (shouldRecord) this.hooks.recordModules.call(this.modules, this.records); - if(shouldRecord) - this.hooks.recordChunks.call(this.chunks, this.records); + if (shouldRecord) this.hooks.recordChunks.call(this.chunks, this.records); this.hooks.beforeHash.call(); this.createHash(); this.hooks.afterHash.call(); - if(shouldRecord) - this.hooks.recordHash.call(this.records); + if (shouldRecord) this.hooks.recordHash.call(this.records); this.hooks.beforeModuleAssets.call(); this.createModuleAssets(); - if(this.hooks.shouldGenerateChunkAssets.call() !== false) { + if (this.hooks.shouldGenerateChunkAssets.call() !== false) { this.hooks.beforeChunkAssets.call(); this.createChunkAssets(); } this.hooks.additionalChunkAssets.call(this.chunks); this.summarizeDependencies(); - if(shouldRecord) - this.hooks.record.call(this, this.records); + if (shouldRecord) this.hooks.record.call(this, this.records); this.hooks.additionalAssets.callAsync(err => { - if(err) { + if (err) { return callback(err); } this.hooks.optimizeChunkAssets.callAsync(this.chunks, err => { - if(err) { + if (err) { return callback(err); } this.hooks.afterOptimizeChunkAssets.call(this.chunks); this.hooks.optimizeAssets.callAsync(this.assets, err => { - if(err) { + if (err) { return callback(err); } this.hooks.afterOptimizeAssets.call(this.assets); - if(this.hooks.needAdditionalSeal.call()) { + if (this.hooks.needAdditionalSeal.call()) { this.unseal(); return this.seal(callback); } @@ -873,16 +966,16 @@ class Compilation extends Tapable { } reportDependencyErrorsAndWarnings(module, blocks) { - for(let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { + for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { const block = blocks[indexBlock]; const dependencies = block.dependencies; - for(let indexDep = 0; indexDep < dependencies.length; indexDep++) { + for (let indexDep = 0; indexDep < dependencies.length; indexDep++) { const d = dependencies[indexDep]; const warnings = d.getWarnings(); - if(warnings) { - for(let indexWar = 0; indexWar < warnings.length; indexWar++) { + if (warnings) { + for (let indexWar = 0; indexWar < warnings.length; indexWar++) { const w = warnings[indexWar]; const warning = new ModuleDependencyWarning(module, w, d.loc); @@ -890,8 +983,8 @@ class Compilation extends Tapable { } } const errors = d.getErrors(); - if(errors) { - for(let indexErr = 0; indexErr < errors.length; indexErr++) { + if (errors) { + for (let indexErr = 0; indexErr < errors.length; indexErr++) { const e = errors[indexErr]; const error = new ModuleDependencyError(module, e, d.loc); @@ -905,39 +998,38 @@ class Compilation extends Tapable { } addChunkInGroup(name, module, loc, request) { - if(name) { + if (name) { const chunkGroup = this.namedChunkGroups.get(name); - if(chunkGroup !== undefined) { - if(module) { + if (chunkGroup !== undefined) { + if (module) { chunkGroup.addOrigin(module, loc, request); } return chunkGroup; } } const chunkGroup = new ChunkGroup(name); - if(module) - chunkGroup.addOrigin(module, loc, request); + if (module) chunkGroup.addOrigin(module, loc, request); const chunk = this.addChunk(name); GraphHelpers.connectChunkGroupAndChunk(chunkGroup, chunk); this.chunkGroups.push(chunkGroup); - if(name) { + if (name) { this.namedChunkGroups.set(name, chunkGroup); } return chunkGroup; } addChunk(name) { - if(name) { + if (name) { const chunk = this.namedChunks.get(name); - if(chunk !== undefined) { + if (chunk !== undefined) { return chunk; } } const chunk = new Chunk(name); this.chunks.push(chunk); - if(name) { + if (name) { this.namedChunks.set(name, chunk); } return chunk; @@ -948,11 +1040,11 @@ class Compilation extends Tapable { const assignIndexToModule = module => { // enter module - if(typeof module.index !== "number") { + if (typeof module.index !== "number") { module.index = _this.nextFreeModuleIndex++; // leave module - queue.push(() => module.index2 = _this.nextFreeModuleIndex2++); + queue.push(() => (module.index2 = _this.nextFreeModuleIndex2++)); // enter it as block assignIndexToDependencyBlock(module); @@ -960,7 +1052,7 @@ class Compilation extends Tapable { }; const assignIndexToDependency = dependency => { - if(dependency.module) { + if (dependency.module) { queue.push(() => assignIndexToModule(dependency.module)); } }; @@ -970,38 +1062,41 @@ class Compilation extends Tapable { const iteratorDependency = d => allDependencies.push(d); - const iteratorBlock = b => queue.push(() => assignIndexToDependencyBlock(b)); + const iteratorBlock = b => + queue.push(() => assignIndexToDependencyBlock(b)); - if(block.variables) { + if (block.variables) { iterationBlockVariable(block.variables, iteratorDependency); } - if(block.dependencies) { + if (block.dependencies) { iterationOfArrayCallback(block.dependencies, iteratorDependency); } - if(block.blocks) { + if (block.blocks) { const blocks = block.blocks; let indexBlock = blocks.length; - while(indexBlock--) { + while (indexBlock--) { iteratorBlock(blocks[indexBlock]); } } let indexAll = allDependencies.length; - while(indexAll--) { + while (indexAll--) { iteratorAllDependencies(allDependencies[indexAll]); } }; - const queue = [() => { - assignIndexToModule(module); - }]; + const queue = [ + () => { + assignIndexToModule(module); + } + ]; const iteratorAllDependencies = d => { queue.push(() => assignIndexToDependency(d)); }; - while(queue.length) { + while (queue.length) { queue.pop()(); } } @@ -1014,32 +1109,32 @@ class Compilation extends Tapable { const enqueueJob = module => { const d = module.depth; - if(typeof d === "number" && d <= depth) return; + if (typeof d === "number" && d <= depth) return; queue.add(module); module.depth = depth; }; const assignDepthToDependency = (dependency, depth) => { - if(dependency.module) { + if (dependency.module) { enqueueJob(dependency.module); } }; const assignDepthToDependencyBlock = block => { - if(block.variables) { + if (block.variables) { iterationBlockVariable(block.variables, assignDepthToDependency); } - if(block.dependencies) { + if (block.dependencies) { iterationOfArrayCallback(block.dependencies, assignDepthToDependency); } - if(block.blocks) { + if (block.blocks) { iterationOfArrayCallback(block.blocks, assignDepthToDependencyBlock); } }; - for(module of queue) { + for (module of queue) { queue.delete(module); depth = module.depth; @@ -1080,10 +1175,12 @@ class Compilation extends Tapable { // 1. We create a chunk for this Block // but only once (blockChunkGroups map) let c = blockChunkGroups.get(b); - if(c === undefined) { + if (c === undefined) { c = this.namedChunkGroups.get(b.chunkName); - if(c && c.isInitial()) { - this.errors.push(new AsyncDependencyToInitialChunkError(b.chunkName, module, b.loc)); + if (c && c.isInitial()) { + this.errors.push( + new AsyncDependencyToInitialChunkError(b.chunkName, module, b.loc) + ); c = chunkGroup; } else { c = this.addChunkInGroup(b.chunkName, module, b.loc, b.request); @@ -1096,7 +1193,7 @@ class Compilation extends Tapable { // 2. We store the Block+Chunk mapping as dependency for the chunk let deps = chunkDependencies.get(chunkGroup); - if(!deps) chunkDependencies.set(chunkGroup, deps = []); + if (!deps) chunkDependencies.set(chunkGroup, (deps = [])); deps.push({ block: b, chunkGroup: c @@ -1115,20 +1212,20 @@ class Compilation extends Tapable { const iteratorDependency = d => { // We skip Dependencies without Reference const ref = d.getReference(); - if(!ref) { + if (!ref) { return; } // We skip Dependencies without Module pointer const refModule = ref.module; - if(!refModule) { + if (!refModule) { return; } // We skip weak Dependencies - if(ref.weak) { + if (ref.weak) { return; } // We connect Module and Chunk when not already done - if(chunk.addModule(refModule)) { + if (chunk.addModule(refModule)) { refModule.addChunk(chunk); // And enqueue the Module for traversal @@ -1143,7 +1240,7 @@ class Compilation extends Tapable { // Iterative traversal of the Module graph // Recursive would be simpler to write but could result in Stack Overflows - while(queue.length) { + while (queue.length) { const queueItem = queue.pop(); module = queueItem.module; block = queueItem.block; @@ -1151,15 +1248,15 @@ class Compilation extends Tapable { chunkGroup = queueItem.chunkGroup; // Traverse all variables, Dependencies and Blocks - if(block.variables) { + if (block.variables) { iterationBlockVariable(block.variables, iteratorDependency); } - if(block.dependencies) { + if (block.dependencies) { iterationOfArrayCallback(block.dependencies, iteratorDependency); } - if(block.blocks) { + if (block.blocks) { iterationOfArrayCallback(block.blocks, iteratorBlock); } } @@ -1168,17 +1265,18 @@ class Compilation extends Tapable { let availableModules; let newAvailableModules; - const queue2 = new Queue(inputChunkGroups.map(chunkGroup => ({ - chunkGroup, - availableModules: new Set() - }))); + const queue2 = new Queue( + inputChunkGroups.map(chunkGroup => ({ + chunkGroup, + availableModules: new Set() + })) + ); // Helper function to check if all modules of a chunk are available const areModulesAvailable = (chunkGroup, availableModules) => { - for(const chunk of chunkGroup.chunks) { - for(const module of chunk.modulesIterable) { - if(!availableModules.has(module)) - return false; + for (const chunk of chunkGroup.chunks) { + for (const module of chunk.modulesIterable) { + if (!availableModules.has(module)) return false; } } return true; @@ -1189,15 +1287,14 @@ class Compilation extends Tapable { // Filter egdes that are not needed because all modules are already available // This also filters circular dependencies in the chunks graph const depChunkGroup = dep.chunkGroup; - if(areModulesAvailable(depChunkGroup, newAvailableModules)) - return false; // break all modules are already available + if (areModulesAvailable(depChunkGroup, newAvailableModules)) return false; // break all modules are already available return true; }; const minAvailableModulesMap = new Map(); // Iterative traversing of the basic chunk graph - while(queue2.length) { + while (queue2.length) { const queueItem = queue2.dequeue(); chunkGroup = queueItem.chunkGroup; availableModules = queueItem.availableModules; @@ -1207,44 +1304,45 @@ class Compilation extends Tapable { // This step calculates the minimal available modules and skips traversal when // the list didn't shrink. let minAvailableModules = minAvailableModulesMap.get(chunkGroup); - if(minAvailableModules === undefined) { + if (minAvailableModules === undefined) { minAvailableModulesMap.set(chunkGroup, new Set(availableModules)); } else { let deletedModules = false; - for(const m of minAvailableModules) { - if(!availableModules.has(m)) { + for (const m of minAvailableModules) { + if (!availableModules.has(m)) { minAvailableModules.delete(m); deletedModules = true; } } - if(!deletedModules) - continue; + if (!deletedModules) continue; availableModules = minAvailableModules; } // 2. Get the edges at this point of the graph const deps = chunkDependencies.get(chunkGroup); - if(!deps) continue; - if(deps.length === 0) continue; + if (!deps) continue; + if (deps.length === 0) continue; // 3. Create a new Set of available modules at this points newAvailableModules = new Set(availableModules); - for(const chunk of chunkGroup.chunks) - for(const m of chunk.modulesIterable) - newAvailableModules.add(m); + for (const chunk of chunkGroup.chunks) + for (const m of chunk.modulesIterable) newAvailableModules.add(m); // 4. Filter edges with available modules const filteredDeps = deps.filter(filterFn); // 5. Foreach remaining edge const nextChunkGroups = new Set(); - for(let i = 0; i < filteredDeps.length; i++) { + for (let i = 0; i < filteredDeps.length; i++) { const dep = filteredDeps[i]; const depChunkGroup = dep.chunkGroup; const depBlock = dep.block; // 6. Connnect block with chunk - GraphHelpers.connectDependenciesBlockAndChunkGroup(depBlock, depChunkGroup); + GraphHelpers.connectDependenciesBlockAndChunkGroup( + depBlock, + depChunkGroup + ); // 7. Connect chunk with parent GraphHelpers.connectChunkGroupParentAndChild(chunkGroup, depChunkGroup); @@ -1253,7 +1351,7 @@ class Compilation extends Tapable { } // 8. Enqueue further traversal - for(const nextChunkGroup of nextChunkGroups) { + for (const nextChunkGroup of nextChunkGroups) { queue2.enqueue({ chunkGroup: nextChunkGroup, availableModules: newAvailableModules @@ -1262,12 +1360,11 @@ class Compilation extends Tapable { } // Remove all unconnected chunk groups - for(const chunkGroup of allCreatedChunkGroups) { - if(chunkGroup.getNumberOfParents() === 0) { - for(const chunk of chunkGroup.chunks) { + for (const chunkGroup of allCreatedChunkGroups) { + if (chunkGroup.getNumberOfParents() === 0) { + for (const chunk of chunkGroup.chunks) { const idx = this.chunks.indexOf(chunk); - if(idx >= 0) - this.chunks.splice(idx, 1); + if (idx >= 0) this.chunks.splice(idx, 1); chunk.remove("unconnected"); } chunkGroup.remove("unconnected"); @@ -1277,35 +1374,37 @@ class Compilation extends Tapable { removeReasonsOfDependencyBlock(module, block) { const iteratorDependency = d => { - if(!d.module) { + if (!d.module) { return; } - if(d.module.removeReason(module, d)) { - for(const chunk of d.module.chunksIterable) { + if (d.module.removeReason(module, d)) { + for (const chunk of d.module.chunksIterable) { this.patchChunksAfterReasonRemoval(d.module, chunk); } } }; - if(block.blocks) { - iterationOfArrayCallback(block.blocks, block => this.removeReasonsOfDependencyBlock(module, block)); + if (block.blocks) { + iterationOfArrayCallback(block.blocks, block => + this.removeReasonsOfDependencyBlock(module, block) + ); } - if(block.dependencies) { + if (block.dependencies) { iterationOfArrayCallback(block.dependencies, iteratorDependency); } - if(block.variables) { + if (block.variables) { iterationBlockVariable(block.variables, iteratorDependency); } } patchChunksAfterReasonRemoval(module, chunk) { - if(!module.hasReasons()) { + if (!module.hasReasons()) { this.removeReasonsOfDependencyBlock(module, module); } - if(!module.hasReasonForChunk(chunk)) { - if(module.removeChunk(chunk)) { + if (!module.hasReasonForChunk(chunk)) { + if (module.removeChunk(chunk)) { this.removeChunkFromDependencies(module, chunk); } } @@ -1313,16 +1412,16 @@ class Compilation extends Tapable { removeChunkFromDependencies(block, chunk) { const iteratorDependency = d => { - if(!d.module) { + if (!d.module) { return; } this.patchChunksAfterReasonRemoval(d.module, chunk); }; const blocks = block.blocks; - for(let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { + for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { const chunks = blocks[indexBlock].chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { const blockChunk = chunks[indexChunk]; chunk.removeChunk(blockChunk); blockChunk.removeParent(chunk); @@ -1330,11 +1429,11 @@ class Compilation extends Tapable { } } - if(block.dependencies) { + if (block.dependencies) { iterationOfArrayCallback(block.dependencies, iteratorDependency); } - if(block.variables) { + if (block.variables) { iterationBlockVariable(block.variables, iteratorDependency); } } @@ -1343,47 +1442,45 @@ class Compilation extends Tapable { const unusedIds = []; let nextFreeModuleId = 0; const usedIds = new Set(); - if(this.usedModuleIds) { - for(const id of this.usedModuleIds) { + if (this.usedModuleIds) { + for (const id of this.usedModuleIds) { usedIds.add(id); } } const modules1 = this.modules; - for(let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) { + for (let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) { const module1 = modules1[indexModule1]; - if(module1.id !== null) { + if (module1.id !== null) { usedIds.add(module1.id); } } - if(usedIds.size > 0) { + if (usedIds.size > 0) { let usedIdMax = -1; - for(const usedIdKey of usedIds) { - if(typeof usedIdKey !== "number") { + for (const usedIdKey of usedIds) { + if (typeof usedIdKey !== "number") { continue; } usedIdMax = Math.max(usedIdMax, usedIdKey); } - let lengthFreeModules = nextFreeModuleId = usedIdMax + 1; + let lengthFreeModules = (nextFreeModuleId = usedIdMax + 1); - while(lengthFreeModules--) { - if(!usedIds.has(lengthFreeModules)) { + while (lengthFreeModules--) { + if (!usedIds.has(lengthFreeModules)) { unusedIds.push(lengthFreeModules); } } } const modules2 = this.modules; - for(let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) { + for (let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) { const module2 = modules2[indexModule2]; - if(module2.id === null) { - if(unusedIds.length > 0) - module2.id = unusedIds.pop(); - else - module2.id = nextFreeModuleId++; + if (module2.id === null) { + if (unusedIds.length > 0) module2.id = unusedIds.pop(); + else module2.id = nextFreeModuleId++; } } } @@ -1392,10 +1489,9 @@ class Compilation extends Tapable { const usedIds = new Set(); // Get used ids from usedChunkIds property (i. e. from records) - if(this.usedChunkIds) { - for(const id of this.usedChunkIds) { - - if(typeof id !== "number") { + if (this.usedChunkIds) { + for (const id of this.usedChunkIds) { + if (typeof id !== "number") { continue; } @@ -1405,11 +1501,11 @@ class Compilation extends Tapable { // Get used ids from existing chunks const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { const chunk = chunks[indexChunk]; const usedIdValue = chunk.id; - if(typeof usedIdValue !== "number") { + if (typeof usedIdValue !== "number") { continue; } @@ -1418,32 +1514,30 @@ class Compilation extends Tapable { // Calculate maximum assigned chunk id let nextFreeChunkId = -1; - for(const id of usedIds) { + for (const id of usedIds) { nextFreeChunkId = Math.max(nextFreeChunkId, id); } nextFreeChunkId++; // Determine free chunk ids from 0 to maximum const unusedIds = []; - if(nextFreeChunkId > 0) { + if (nextFreeChunkId > 0) { let index = nextFreeChunkId; - while(index--) { - if(!usedIds.has(index)) { + while (index--) { + if (!usedIds.has(index)) { unusedIds.push(index); } } } // Assign ids to chunk which has no id - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { const chunk = chunks[indexChunk]; - if(chunk.id === null) { - if(unusedIds.length > 0) - chunk.id = unusedIds.pop(); - else - chunk.id = nextFreeChunkId++; + if (chunk.id === null) { + if (unusedIds.length > 0) chunk.id = unusedIds.pop(); + else chunk.id = nextFreeChunkId++; } - if(!chunk.ids) { + if (!chunk.ids) { chunk.ids = [chunk.id]; } } @@ -1453,37 +1547,41 @@ class Compilation extends Tapable { this.modules.sort(byIdOrIdentifier); const modules = this.modules; - for(let indexModule = 0; indexModule < modules.length; indexModule++) { + for (let indexModule = 0; indexModule < modules.length; indexModule++) { modules[indexModule].sortItems(false); } const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { chunks[indexChunk].sortItems(false); } } sortItemsWithChunkIds() { - for(const chunkGroup of this.chunkGroups) { + for (const chunkGroup of this.chunkGroups) { chunkGroup.sortItems(); } this.chunks.sort(byId); - for(let indexModule = 0; indexModule < this.modules.length; indexModule++) { + for ( + let indexModule = 0; + indexModule < this.modules.length; + indexModule++ + ) { this.modules[indexModule].sortItems(true); } const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { chunks[indexChunk].sortItems(true); } const byMessage = (a, b) => { const ma = `${a.message}`; const mb = `${b.message}`; - if(ma < mb) return -1; - if(mb < ma) return 1; + if (ma < mb) return -1; + if (mb < ma) return 1; return 0; }; @@ -1496,7 +1594,11 @@ class Compilation extends Tapable { this.contextDependencies = new SortableSet(); this.missingDependencies = new SortableSet(); - for(let indexChildren = 0; indexChildren < this.children.length; indexChildren++) { + for ( + let indexChildren = 0; + indexChildren < this.children.length; + indexChildren++ + ) { const child = this.children[indexChildren]; addAllToSet(this.fileDependencies, child.fileDependencies); @@ -1504,18 +1606,29 @@ class Compilation extends Tapable { addAllToSet(this.missingDependencies, child.missingDependencies); } - for(let indexModule = 0; indexModule < this.modules.length; indexModule++) { + for ( + let indexModule = 0; + indexModule < this.modules.length; + indexModule++ + ) { const module = this.modules[indexModule]; - if(module.buildInfo.fileDependencies) { + if (module.buildInfo.fileDependencies) { addAllToSet(this.fileDependencies, module.buildInfo.fileDependencies); } - if(module.buildInfo.contextDependencies) { - addAllToSet(this.contextDependencies, module.buildInfo.contextDependencies); + if (module.buildInfo.contextDependencies) { + addAllToSet( + this.contextDependencies, + module.buildInfo.contextDependencies + ); } } - for(const error of this.errors) { - if(typeof error.missing === "object" && error.missing && error.missing[Symbol.iterator]) { + for (const error of this.errors) { + if ( + typeof error.missing === "object" && + error.missing && + error.missing[Symbol.iterator] + ) { addAllToSet(this.missingDependencies, error.missing); } } @@ -1530,16 +1643,16 @@ class Compilation extends Tapable { const hashDigest = outputOptions.hashDigest; const hashDigestLength = outputOptions.hashDigestLength; const hash = createHash(hashFunction); - if(outputOptions.hashSalt) - hash.update(outputOptions.hashSalt); + if (outputOptions.hashSalt) hash.update(outputOptions.hashSalt); this.mainTemplate.updateHash(hash); this.chunkTemplate.updateHash(hash); - for(const key of Object.keys(this.moduleTemplates).sort()) this.moduleTemplates[key].updateHash(hash); - for(const child of this.children) hash.update(child.hash); - for(const warning of this.warnings) hash.update(`${warning.message}`); - for(const error of this.errors) hash.update(`${error.message}`); + for (const key of Object.keys(this.moduleTemplates).sort()) + this.moduleTemplates[key].updateHash(hash); + for (const child of this.children) hash.update(child.hash); + for (const warning of this.warnings) hash.update(`${warning.message}`); + for (const error of this.errors) hash.update(`${error.message}`); const modules = this.modules; - for(let i = 0; i < modules.length; i++) { + for (let i = 0; i < modules.length; i++) { const module = modules[i]; const moduleHash = createHash(hashFunction); module.updateHash(moduleHash); @@ -1556,17 +1669,16 @@ class Compilation extends Tapable { chunks.sort((a, b) => { const aEntry = a.hasRuntime(); const bEntry = b.hasRuntime(); - if(aEntry && !bEntry) return 1; - if(!aEntry && bEntry) return -1; + if (aEntry && !bEntry) return 1; + if (!aEntry && bEntry) return -1; return 0; }); - for(let i = 0; i < chunks.length; i++) { + for (let i = 0; i < chunks.length; i++) { const chunk = chunks[i]; const chunkHash = createHash(hashFunction); - if(outputOptions.hashSalt) - chunkHash.update(outputOptions.hashSalt); + if (outputOptions.hashSalt) chunkHash.update(outputOptions.hashSalt); chunk.updateHash(chunkHash); - if(chunk.hasRuntime()) { + if (chunk.hasRuntime()) { this.mainTemplate.updateHashForChunk(chunkHash, chunk); } else { this.chunkTemplate.updateHashForChunk(chunkHash, chunk); @@ -1593,10 +1705,10 @@ class Compilation extends Tapable { } createModuleAssets() { - for(let i = 0; i < this.modules.length; i++) { + for (let i = 0; i < this.modules.length; i++) { const module = this.modules[i]; - if(module.buildInfo.assets) { - for(const assetName of Object.keys(module.buildInfo.assets)) { + if (module.buildInfo.assets) { + for (const assetName of Object.keys(module.buildInfo.assets)) { const fileName = this.getPath(assetName); this.assets[fileName] = module.buildInfo.assets[assetName]; this.hooks.moduleAsset.call(module, fileName); @@ -1608,14 +1720,16 @@ class Compilation extends Tapable { createChunkAssets() { const outputOptions = this.outputOptions; const cachedSourceMap = new Map(); - for(let i = 0; i < this.chunks.length; i++) { + for (let i = 0; i < this.chunks.length; i++) { const chunk = this.chunks[i]; chunk.files = []; let source; let file; let filenameTemplate; try { - const template = chunk.hasRuntime() ? this.mainTemplate : this.chunkTemplate; + const template = chunk.hasRuntime() + ? this.mainTemplate + : this.chunkTemplate; const manifest = template.getRenderManifest({ chunk, hash: this.hash, @@ -1624,18 +1738,22 @@ class Compilation extends Tapable { moduleTemplates: this.moduleTemplates, dependencyTemplates: this.dependencyTemplates }); // [{ render(), filenameTemplate, pathOptions, identifier, hash }] - for(const fileManifest of manifest) { + for (const fileManifest of manifest) { const cacheName = fileManifest.identifier; const usedHash = fileManifest.hash; filenameTemplate = fileManifest.filenameTemplate; - if(this.cache && this.cache[cacheName] && this.cache[cacheName].hash === usedHash) { + if ( + this.cache && + this.cache[cacheName] && + this.cache[cacheName].hash === usedHash + ) { source = this.cache[cacheName].source; } else { source = fileManifest.render(); // Ensure that source is a cached source to avoid additional cost because of repeated access - if(!(source instanceof CachedSource)) { + if (!(source instanceof CachedSource)) { const cacheEntry = cachedSourceMap.get(source); - if(cacheEntry) { + if (cacheEntry) { source = cacheEntry; } else { const cachedSource = new CachedSource(source); @@ -1643,7 +1761,7 @@ class Compilation extends Tapable { source = cachedSource; } } - if(this.cache) { + if (this.cache) { this.cache[cacheName] = { hash: usedHash, source @@ -1651,14 +1769,18 @@ class Compilation extends Tapable { } } file = this.getPath(filenameTemplate, fileManifest.pathOptions); - if(this.assets[file] && this.assets[file] !== source) - throw new Error(`Conflict: Multiple assets emit to the same filename ${file}`); + if (this.assets[file] && this.assets[file] !== source) + throw new Error( + `Conflict: Multiple assets emit to the same filename ${file}` + ); this.assets[file] = source; chunk.files.push(file); this.hooks.chunkAsset.call(chunk, file); } - } catch(err) { - this.errors.push(new ChunkRenderError(chunk, file || filenameTemplate, err)); + } catch (err) { + this.errors.push( + new ChunkRenderError(chunk, file || filenameTemplate, err) + ); } } } @@ -1670,31 +1792,39 @@ class Compilation extends Tapable { } createChildCompiler(name, outputOptions, plugins) { - const idx = (this.childrenCounters[name] || 0); + const idx = this.childrenCounters[name] || 0; this.childrenCounters[name] = idx + 1; - return this.compiler.createChildCompiler(this, name, idx, outputOptions, plugins); + return this.compiler.createChildCompiler( + this, + name, + idx, + outputOptions, + plugins + ); } checkConstraints() { const usedIds = new Set(); const modules = this.modules; - for(let indexModule = 0; indexModule < modules.length; indexModule++) { + for (let indexModule = 0; indexModule < modules.length; indexModule++) { const moduleId = modules[indexModule].id; - if(moduleId === null) continue; - if(usedIds.has(moduleId)) + if (moduleId === null) continue; + if (usedIds.has(moduleId)) throw new Error(`checkConstraints: duplicate module id ${moduleId}`); usedIds.add(moduleId); } const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { const chunk = chunks[indexChunk]; - if(chunks.indexOf(chunk) !== indexChunk) - throw new Error(`checkConstraints: duplicate chunk in compilation ${chunk.debugId}`); + if (chunks.indexOf(chunk) !== indexChunk) + throw new Error( + `checkConstraints: duplicate chunk in compilation ${chunk.debugId}` + ); } - for(const chunkGroup of this.chunkGroups) { + for (const chunkGroup of this.chunkGroups) { chunkGroup.checkConstraints(); } } @@ -1702,7 +1832,9 @@ class Compilation extends Tapable { // TODO remove in webpack 5 Compilation.prototype.applyPlugins = util.deprecate(function(name, ...args) { - this.hooks[name.replace(/[- ]([a-z])/g, match => match[1].toUpperCase())].call(...args); + this.hooks[ + name.replace(/[- ]([a-z])/g, match => match[1].toUpperCase()) + ].call(...args); }, "Compilation.applyPlugins is deprecated. Use new API on `.hooks` instead"); // TODO remove in webpack 5 diff --git a/lib/Compiler.js b/lib/Compiler.js index 2787734e6..18c9307e9 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -53,10 +53,10 @@ class Compiler extends Tapable { afterEnvironment: new SyncHook([]), afterPlugins: new SyncHook(["compiler"]), afterResolvers: new SyncHook(["compiler"]), - entryOption: new SyncBailHook(["context", "entry"]), + entryOption: new SyncBailHook(["context", "entry"]) }; this._pluginCompat.tap("Compiler", options => { - switch(options.name) { + switch (options.name) { case "additional-pass": case "before-run": case "run": @@ -87,64 +87,40 @@ class Compiler extends Tapable { // TODO remove in webpack 5 this.resolvers = { normal: { - plugins: util.deprecate( - (hook, fn) => { - this.resolverFactory.plugin("resolver normal", resolver => { - resolver.plugin(hook, fn); - }); - }, - "webpack: Using compiler.resolvers.normal is deprecated.\n" + - "Use compiler.resolverFactory.plugin(\"resolver normal\", resolver => {\n resolver.plugin(/* ... */);\n}); instead." - ), - apply: util.deprecate( - (...args) => { - this.resolverFactory.plugin("resolver normal", resolver => { - resolver.apply(...args); - }); - }, - "webpack: Using compiler.resolvers.normal is deprecated.\n" + - "Use compiler.resolverFactory.plugin(\"resolver normal\", resolver => {\n resolver.apply(/* ... */);\n}); instead." - ) + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver normal", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver normal", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.apply(/* ... */);\n}); instead.') }, loader: { - plugins: util.deprecate( - (hook, fn) => { - this.resolverFactory.plugin("resolver loader", resolver => { - resolver.plugin(hook, fn); - }); - }, - "webpack: Using compiler.resolvers.loader is deprecated.\n" + - "Use compiler.resolverFactory.plugin(\"resolver loader\", resolver => {\n resolver.plugin(/* ... */);\n}); instead." - ), - apply: util.deprecate( - (...args) => { - this.resolverFactory.plugin("resolver loader", resolver => { - resolver.apply(...args); - }); - }, - "webpack: Using compiler.resolvers.loader is deprecated.\n" + - "Use compiler.resolverFactory.plugin(\"resolver loader\", resolver => {\n resolver.apply(/* ... */);\n}); instead." - ) + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver loader", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver loader", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.apply(/* ... */);\n}); instead.') }, context: { - plugins: util.deprecate( - (hook, fn) => { - this.resolverFactory.plugin("resolver context", resolver => { - resolver.plugin(hook, fn); - }); - }, - "webpack: Using compiler.resolvers.context is deprecated.\n" + - "Use compiler.resolverFactory.plugin(\"resolver context\", resolver => {\n resolver.plugin(/* ... */);\n}); instead." - ), - apply: util.deprecate( - (...args) => { - this.resolverFactory.plugin("resolver context", resolver => { - resolver.apply(...args); - }); - }, - "webpack: Using compiler.resolvers.context is deprecated.\n" + - "Use compiler.resolverFactory.plugin(\"resolver context\", resolver => {\n resolver.apply(/* ... */);\n}); instead." - ) + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver context", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver context", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.apply(/* ... */);\n}); instead.') } }; @@ -165,33 +141,33 @@ class Compiler extends Tapable { const startTime = Date.now(); const onCompiled = (err, compilation) => { - if(err) return callback(err); + if (err) return callback(err); - if(this.hooks.shouldEmit.call(compilation) === false) { + if (this.hooks.shouldEmit.call(compilation) === false) { const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { - if(err) return callback(err); + if (err) return callback(err); return callback(null, stats); }); return; } this.emitAssets(compilation, err => { - if(err) return callback(err); + if (err) return callback(err); - if(compilation.hooks.needAdditionalPass.call()) { + if (compilation.hooks.needAdditionalPass.call()) { compilation.needAdditionalPass = true; const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { - if(err) return callback(err); + if (err) return callback(err); this.hooks.additionalPass.callAsync(err => { - if(err) return callback(err); + if (err) return callback(err); this.compile(onCompiled); }); }); @@ -199,13 +175,13 @@ class Compiler extends Tapable { } this.emitRecords(err => { - if(err) return callback(err); + if (err) return callback(err); const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { - if(err) return callback(err); + if (err) return callback(err); return callback(null, stats); }); }); @@ -213,13 +189,13 @@ class Compiler extends Tapable { }; this.hooks.beforeRun.callAsync(this, err => { - if(err) return callback(err); + if (err) return callback(err); this.hooks.run.callAsync(this, err => { - if(err) return callback(err); + if (err) return callback(err); this.readRecords(err => { - if(err) return callback(err); + if (err) return callback(err); this.compile(onCompiled); }); @@ -229,14 +205,17 @@ class Compiler extends Tapable { runAsChild(callback) { this.compile((err, compilation) => { - if(err) return callback(err); + if (err) return callback(err); this.parentCompilation.children.push(compilation); - for(const name of Object.keys(compilation.assets)) { + for (const name of Object.keys(compilation.assets)) { this.parentCompilation.assets[name] = compilation.assets[name]; } - const entries = Array.from(compilation.entrypoints.values(), ep => ep.chunks).reduce((array, chunks) => { + const entries = Array.from( + compilation.entrypoints.values(), + ep => ep.chunks + ).reduce((array, chunks) => { return array.concat(chunks); }, []); @@ -245,101 +224,114 @@ class Compiler extends Tapable { } purgeInputFileSystem() { - if(this.inputFileSystem && this.inputFileSystem.purge) + if (this.inputFileSystem && this.inputFileSystem.purge) this.inputFileSystem.purge(); } emitAssets(compilation, callback) { let outputPath; - const emitFiles = (err) => { - if(err) return callback(err); + const emitFiles = err => { + if (err) return callback(err); - asyncLib.forEach(compilation.assets, (source, file, callback) => { + asyncLib.forEach( + compilation.assets, + (source, file, callback) => { + let targetFile = file; + const queryStringIdx = targetFile.indexOf("?"); + if (queryStringIdx >= 0) { + targetFile = targetFile.substr(0, queryStringIdx); + } - let targetFile = file; - const queryStringIdx = targetFile.indexOf("?"); - if(queryStringIdx >= 0) { - targetFile = targetFile.substr(0, queryStringIdx); - } + const writeOut = err => { + if (err) return callback(err); + const targetPath = this.outputFileSystem.join( + outputPath, + targetFile + ); + if (source.existsAt === targetPath) { + source.emitted = false; + return callback(); + } + let content = source.source(); + + if (!Buffer.isBuffer(content)) { + content = Buffer.from(content, "utf8"); + } + + source.existsAt = targetPath; + source.emitted = true; + this.outputFileSystem.writeFile(targetPath, content, callback); + }; + + if (targetFile.match(/\/|\\/)) { + const dir = path.dirname(targetFile); + this.outputFileSystem.mkdirp( + this.outputFileSystem.join(outputPath, dir), + writeOut + ); + } else writeOut(); + }, + err => { + if (err) return callback(err); + + this.hooks.afterEmit.callAsync(compilation, err => { + if (err) return callback(err); - const writeOut = (err) => { - if(err) return callback(err); - const targetPath = this.outputFileSystem.join(outputPath, targetFile); - if(source.existsAt === targetPath) { - source.emitted = false; return callback(); - } - let content = source.source(); - - if(!Buffer.isBuffer(content)) { - content = Buffer.from(content, "utf8"); - } - - source.existsAt = targetPath; - source.emitted = true; - this.outputFileSystem.writeFile(targetPath, content, callback); - }; - - if(targetFile.match(/\/|\\/)) { - const dir = path.dirname(targetFile); - this.outputFileSystem.mkdirp(this.outputFileSystem.join(outputPath, dir), writeOut); - } else writeOut(); - - }, err => { - if(err) return callback(err); - - this.hooks.afterEmit.callAsync(compilation, err => { - if(err) return callback(err); - - return callback(); - }); - }); + }); + } + ); }; this.hooks.emit.callAsync(compilation, err => { - if(err) return callback(err); + if (err) return callback(err); outputPath = compilation.getPath(this.outputPath); this.outputFileSystem.mkdirp(outputPath, emitFiles); }); } emitRecords(callback) { - if(!this.recordsOutputPath) return callback(); + if (!this.recordsOutputPath) return callback(); const idx1 = this.recordsOutputPath.lastIndexOf("/"); const idx2 = this.recordsOutputPath.lastIndexOf("\\"); let recordsOutputPathDirectory = null; - if(idx1 > idx2) recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1); - if(idx1 < idx2) recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2); + if (idx1 > idx2) + recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1); + if (idx1 < idx2) + recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2); const writeFile = () => { - this.outputFileSystem.writeFile(this.recordsOutputPath, JSON.stringify(this.records, undefined, 2), callback); + this.outputFileSystem.writeFile( + this.recordsOutputPath, + JSON.stringify(this.records, undefined, 2), + callback + ); }; - if(!recordsOutputPathDirectory) - return writeFile(); + if (!recordsOutputPathDirectory) return writeFile(); this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => { - if(err) return callback(err); + if (err) return callback(err); writeFile(); }); } readRecords(callback) { - if(!this.recordsInputPath) { + if (!this.recordsInputPath) { this.records = {}; return callback(); } this.inputFileSystem.stat(this.recordsInputPath, err => { // It doesn't exist // We can ignore this. - if(err) return callback(); + if (err) return callback(); this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => { - if(err) return callback(err); + if (err) return callback(err); try { this.records = JSON.parse(content.toString("utf-8")); - } catch(e) { + } catch (e) { e.message = "Cannot parse records: " + e.message; return callback(e); } @@ -349,14 +341,30 @@ class Compiler extends Tapable { }); } - createChildCompiler(compilation, compilerName, compilerIndex, outputOptions, plugins) { + createChildCompiler( + compilation, + compilerName, + compilerIndex, + outputOptions, + plugins + ) { const childCompiler = new Compiler(this.context); - if(Array.isArray(plugins)) { - for(const plugin of plugins) plugin.apply(childCompiler); + if (Array.isArray(plugins)) { + for (const plugin of plugins) plugin.apply(childCompiler); } - for(const name in this.hooks) { - if(!["make", "compile", "emit", "afterEmit", "invalid", "done", "thisCompilation"].includes(name)) { - if(childCompiler.hooks[name]) + for (const name in this.hooks) { + if ( + ![ + "make", + "compile", + "emit", + "afterEmit", + "invalid", + "done", + "thisCompilation" + ].includes(name) + ) { + if (childCompiler.hooks[name]) childCompiler.hooks[name].taps = this.hooks[name].taps.slice(); } } @@ -369,20 +377,24 @@ class Compiler extends Tapable { childCompiler.contextTimestamps = this.contextTimestamps; const relativeCompilerName = makePathsRelative(this.context, compilerName); - if(!this.records[relativeCompilerName]) this.records[relativeCompilerName] = []; - if(this.records[relativeCompilerName][compilerIndex]) + if (!this.records[relativeCompilerName]) + this.records[relativeCompilerName] = []; + if (this.records[relativeCompilerName][compilerIndex]) childCompiler.records = this.records[relativeCompilerName][compilerIndex]; - else - this.records[relativeCompilerName].push(childCompiler.records = {}); + else this.records[relativeCompilerName].push((childCompiler.records = {})); childCompiler.options = Object.create(this.options); childCompiler.options.output = Object.create(childCompiler.options.output); - for(const name in outputOptions) { + for (const name in outputOptions) { childCompiler.options.output[name] = outputOptions[name]; } childCompiler.parentCompilation = compilation; - compilation.hooks.childCompiler.call(childCompiler, compilerName, compilerIndex); + compilation.hooks.childCompiler.call( + childCompiler, + compilerName, + compilerIndex + ); return childCompiler; } @@ -408,13 +420,20 @@ class Compiler extends Tapable { } createNormalModuleFactory() { - const normalModuleFactory = new NormalModuleFactory(this.options.context, this.resolverFactory, this.options.module || {}); + const normalModuleFactory = new NormalModuleFactory( + this.options.context, + this.resolverFactory, + this.options.module || {} + ); this.hooks.normalModuleFactory.call(normalModuleFactory); return normalModuleFactory; } createContextModuleFactory() { - const contextModuleFactory = new ContextModuleFactory(this.resolverFactory, this.inputFileSystem); + const contextModuleFactory = new ContextModuleFactory( + this.resolverFactory, + this.inputFileSystem + ); this.hooks.contextModuleFactory.call(contextModuleFactory); return contextModuleFactory; } @@ -431,22 +450,22 @@ class Compiler extends Tapable { compile(callback) { const params = this.newCompilationParams(); this.hooks.beforeCompile.callAsync(params, err => { - if(err) return callback(err); + if (err) return callback(err); this.hooks.compile.call(params); const compilation = this.newCompilation(params); this.hooks.make.callAsync(compilation, err => { - if(err) return callback(err); + if (err) return callback(err); compilation.finish(); compilation.seal(err => { - if(err) return callback(err); + if (err) return callback(err); this.hooks.afterCompile.callAsync(compilation, err => { - if(err) return callback(err); + if (err) return callback(err); return callback(null, compilation); }); diff --git a/lib/ConstPlugin.js b/lib/ConstPlugin.js index 05df375a1..736838353 100644 --- a/lib/ConstPlugin.js +++ b/lib/ConstPlugin.js @@ -7,29 +7,27 @@ const ConstDependency = require("./dependencies/ConstDependency"); const NullFactory = require("./NullFactory"); const ParserHelpers = require("./ParserHelpers"); -const getQuery = (request) => { +const getQuery = request => { const i = request.indexOf("?"); return i !== -1 ? request.substr(i) : ""; }; const collectDeclaration = (declarations, pattern) => { const stack = [pattern]; - while(stack.length > 0) { + while (stack.length > 0) { const node = stack.pop(); - switch(node.type) { + switch (node.type) { case "Identifier": declarations.add(node.name); break; case "ArrayPattern": - for(const element of node.elements) - if(element) stack.push(element); + for (const element of node.elements) if (element) stack.push(element); break; case "AssignmentPattern": stack.push(node.left); break; case "ObjectPattern": - for(const property of node.properties) - stack.push(property.value); + for (const property of node.properties) stack.push(property.value); break; case "RestElement": stack.push(node.argument); @@ -41,17 +39,15 @@ const collectDeclaration = (declarations, pattern) => { const getHoistedDeclarations = (branch, includeFunctionDeclarations) => { const declarations = new Set(); const stack = [branch]; - while(stack.length > 0) { + while (stack.length > 0) { const node = stack.pop(); // Some node could be `null` or `undefined`. - if(!node) - continue; - switch(node.type) { + if (!node) continue; + switch (node.type) { // Walk through control statements to look for hoisted declarations. // Some branches are skipped since they do not allow declarations. case "BlockStatement": - for(const stmt of node.body) - stack.push(stmt); + for (const stmt of node.body) stack.push(stmt); break; case "IfStatement": stack.push(node.consequent); @@ -72,23 +68,21 @@ const getHoistedDeclarations = (branch, includeFunctionDeclarations) => { stack.push(node.body); break; case "SwitchStatement": - for(const cs of node.cases) - for(const consequent of cs.consequent) - stack.push(consequent); + for (const cs of node.cases) + for (const consequent of cs.consequent) stack.push(consequent); break; case "TryStatement": stack.push(node.block); - if(node.handler) - stack.push(node.handler.body); + if (node.handler) stack.push(node.handler.body); stack.push(node.finalizer); break; case "FunctionDeclaration": - if(includeFunctionDeclarations) + if (includeFunctionDeclarations) collectDeclaration(declarations, node.id); break; case "VariableDeclaration": - if(node.kind === "var") - for(const decl of node.declarations) + if (node.kind === "var") + for (const decl of node.declarations) collectDeclaration(declarations, decl.id); break; } @@ -98,118 +92,150 @@ const getHoistedDeclarations = (branch, includeFunctionDeclarations) => { class ConstPlugin { apply(compiler) { - compiler.hooks.compilation.tap("ConstPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compiler.hooks.compilation.tap( + "ConstPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - const handler = parser => { - parser.hooks.statementIf.tap("ConstPlugin", statement => { - const param = parser.evaluateExpression(statement.test); - const bool = param.asBool(); - if(typeof bool === "boolean") { - if(statement.test.type !== "Literal") { - const dep = new ConstDependency(`${bool}`, param.range); - dep.loc = statement.loc; - parser.state.current.addDependency(dep); - } - const branchToRemove = bool ? statement.alternate : statement.consequent; - if(branchToRemove) { - // Before removing the dead branch, the hoisted declarations - // must be collected. - // - // Given the following code: - // - // if (true) f() else g() - // if (false) { - // function f() {} - // const g = function g() {} - // if (someTest) { - // let a = 1 - // var x, {y, z} = obj - // } - // } else { - // … - // } - // - // the generated code is: - // - // if (true) f() else {} - // if (false) { - // var f, x, y, z; (in loose mode) - // var x, y, z; (in strict mode) - // } else { - // … - // } - // - // NOTE: When code runs in strict mode, `var` declarations - // are hoisted but `function` declarations don't. - // - let declarations; - if(parser.scope.isStrict) { - // If the code runs in strict mode, variable declarations - // using `var` must be hoisted. - declarations = getHoistedDeclarations(branchToRemove, false); - } else { - // Otherwise, collect all hoisted declaration. - declarations = getHoistedDeclarations(branchToRemove, true); + const handler = parser => { + parser.hooks.statementIf.tap("ConstPlugin", statement => { + const param = parser.evaluateExpression(statement.test); + const bool = param.asBool(); + if (typeof bool === "boolean") { + if (statement.test.type !== "Literal") { + const dep = new ConstDependency(`${bool}`, param.range); + dep.loc = statement.loc; + parser.state.current.addDependency(dep); } - let replacement; - if(declarations.length > 0) { - replacement = `{ var ${declarations.join(", ")}; }`; - } else { - replacement = "{}"; + const branchToRemove = bool + ? statement.alternate + : statement.consequent; + if (branchToRemove) { + // Before removing the dead branch, the hoisted declarations + // must be collected. + // + // Given the following code: + // + // if (true) f() else g() + // if (false) { + // function f() {} + // const g = function g() {} + // if (someTest) { + // let a = 1 + // var x, {y, z} = obj + // } + // } else { + // … + // } + // + // the generated code is: + // + // if (true) f() else {} + // if (false) { + // var f, x, y, z; (in loose mode) + // var x, y, z; (in strict mode) + // } else { + // … + // } + // + // NOTE: When code runs in strict mode, `var` declarations + // are hoisted but `function` declarations don't. + // + let declarations; + if (parser.scope.isStrict) { + // If the code runs in strict mode, variable declarations + // using `var` must be hoisted. + declarations = getHoistedDeclarations(branchToRemove, false); + } else { + // Otherwise, collect all hoisted declaration. + declarations = getHoistedDeclarations(branchToRemove, true); + } + let replacement; + if (declarations.length > 0) { + replacement = `{ var ${declarations.join(", ")}; }`; + } else { + replacement = "{}"; + } + const dep = new ConstDependency( + replacement, + branchToRemove.range + ); + dep.loc = branchToRemove.loc; + parser.state.current.addDependency(dep); } - const dep = new ConstDependency(replacement, branchToRemove.range); - dep.loc = branchToRemove.loc; - parser.state.current.addDependency(dep); + return bool; } - return bool; - } - }); - parser.hooks.expressionConditionalOperator.tap("ConstPlugin", expression => { - const param = parser.evaluateExpression(expression.test); - const bool = param.asBool(); - if(typeof bool === "boolean") { - if(expression.test.type !== "Literal") { - const dep = new ConstDependency(` ${bool}`, param.range); - dep.loc = expression.loc; - parser.state.current.addDependency(dep); + }); + parser.hooks.expressionConditionalOperator.tap( + "ConstPlugin", + expression => { + const param = parser.evaluateExpression(expression.test); + const bool = param.asBool(); + if (typeof bool === "boolean") { + if (expression.test.type !== "Literal") { + const dep = new ConstDependency(` ${bool}`, param.range); + dep.loc = expression.loc; + parser.state.current.addDependency(dep); + } + // Expressions do not hoist. + // It is safe to remove the dead branch. + // + // Given the following code: + // + // false ? someExpression() : otherExpression(); + // + // the generated code is: + // + // false ? undefined : otherExpression(); + // + const branchToRemove = bool + ? expression.alternate + : expression.consequent; + const dep = new ConstDependency( + "undefined", + branchToRemove.range + ); + dep.loc = branchToRemove.loc; + parser.state.current.addDependency(dep); + return bool; + } } - // Expressions do not hoist. - // It is safe to remove the dead branch. - // - // Given the following code: - // - // false ? someExpression() : otherExpression(); - // - // the generated code is: - // - // false ? undefined : otherExpression(); - // - const branchToRemove = bool ? expression.alternate : expression.consequent; - const dep = new ConstDependency("undefined", branchToRemove.range); - dep.loc = branchToRemove.loc; - parser.state.current.addDependency(dep); - return bool; - } - }); - parser.hooks.evaluateIdentifier.for("__resourceQuery").tap("ConstPlugin", expr => { - if(!parser.state.module) return; - return ParserHelpers.evaluateToString(getQuery(parser.state.module.resource))(expr); - }); - parser.hooks.expression.for("__resourceQuery").tap("ConstPlugin", () => { - if(!parser.state.module) return; - parser.state.current.addVariable("__resourceQuery", JSON.stringify(getQuery(parser.state.module.resource))); - return true; - }); - }; + ); + parser.hooks.evaluateIdentifier + .for("__resourceQuery") + .tap("ConstPlugin", expr => { + if (!parser.state.module) return; + return ParserHelpers.evaluateToString( + getQuery(parser.state.module.resource) + )(expr); + }); + parser.hooks.expression + .for("__resourceQuery") + .tap("ConstPlugin", () => { + if (!parser.state.module) return; + parser.state.current.addVariable( + "__resourceQuery", + JSON.stringify(getQuery(parser.state.module.resource)) + ); + return true; + }); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("ConstPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ConstPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("ConstPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ConstPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ConstPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ConstPlugin", handler); + } + ); } } diff --git a/lib/ContextExclusionPlugin.js b/lib/ContextExclusionPlugin.js index 6b149f095..1333e9dbc 100644 --- a/lib/ContextExclusionPlugin.js +++ b/lib/ContextExclusionPlugin.js @@ -6,8 +6,8 @@ class ContextExclusionPlugin { } apply(compiler) { - compiler.hooks.contextModuleFactory.tap("ContextExclusionPlugin", (cmf) => { - cmf.hooks.contextModuleFiles.tap("ContextExclusionPlugin", (files) => { + compiler.hooks.contextModuleFactory.tap("ContextExclusionPlugin", cmf => { + cmf.hooks.contextModuleFiles.tap("ContextExclusionPlugin", files => { return files.filter(filePath => !this.negativeMatcher.test(filePath)); }); }); diff --git a/lib/ContextModule.js b/lib/ContextModule.js index eb68215b6..6163225f1 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -20,7 +20,7 @@ class ContextModule extends Module { let resource; let resourceQuery; const queryIdx = options.resource.indexOf("?"); - if(queryIdx >= 0) { + if (queryIdx >= 0) { resource = options.resource.substr(0, queryIdx); resourceQuery = options.resource.substr(queryIdx); } else { @@ -36,13 +36,13 @@ class ContextModule extends Module { resource: resource, resourceQuery: resourceQuery }); - if(options.resolveOptions !== undefined) + if (options.resolveOptions !== undefined) this.resolveOptions = options.resolveOptions; // Info from Build this._contextDependencies = new Set([this.context]); - if(typeof options.mode !== "string") + if (typeof options.mode !== "string") throw new Error("options.mode is a required option"); } @@ -53,77 +53,66 @@ class ContextModule extends Module { } contextify(context, request) { - return request.split("!").map(subrequest => { - let rp = path.relative(context, subrequest); - if(path.sep === "\\") - rp = rp.replace(/\\/g, "/"); - if(rp.indexOf("../") !== 0) - rp = "./" + rp; - return rp; - }).join("!"); + return request + .split("!") + .map(subrequest => { + let rp = path.relative(context, subrequest); + if (path.sep === "\\") rp = rp.replace(/\\/g, "/"); + if (rp.indexOf("../") !== 0) rp = "./" + rp; + return rp; + }) + .join("!"); } identifier() { let identifier = this.context; - if(this.options.resourceQuery) + if (this.options.resourceQuery) identifier += ` ${this.options.resourceQuery}`; - if(this.options.mode) - identifier += ` ${this.options.mode}`; - if(!this.options.recursive) - identifier += " nonrecursive"; - if(this.options.addon) - identifier += ` ${this.options.addon}`; - if(this.options.regExp) - identifier += ` ${this.options.regExp}`; - if(this.options.include) - identifier += ` include: ${this.options.include}`; - if(this.options.exclude) - identifier += ` exclude: ${this.options.exclude}`; - if(this.options.namespaceObject === "strict") + if (this.options.mode) identifier += ` ${this.options.mode}`; + if (!this.options.recursive) identifier += " nonrecursive"; + if (this.options.addon) identifier += ` ${this.options.addon}`; + if (this.options.regExp) identifier += ` ${this.options.regExp}`; + if (this.options.include) identifier += ` include: ${this.options.include}`; + if (this.options.exclude) identifier += ` exclude: ${this.options.exclude}`; + if (this.options.namespaceObject === "strict") identifier += " strict namespace object"; - else if(this.options.namespaceObject) - identifier += " namespace object"; + else if (this.options.namespaceObject) identifier += " namespace object"; return identifier; } readableIdentifier(requestShortener) { let identifier = requestShortener.shorten(this.context); - if(this.options.resourceQuery) + if (this.options.resourceQuery) identifier += ` ${this.options.resourceQuery}`; - if(this.options.mode) - identifier += ` ${this.options.mode}`; - if(!this.options.recursive) - identifier += " nonrecursive"; - if(this.options.addon) + if (this.options.mode) identifier += ` ${this.options.mode}`; + if (!this.options.recursive) identifier += " nonrecursive"; + if (this.options.addon) identifier += ` ${requestShortener.shorten(this.options.addon)}`; - if(this.options.regExp) + if (this.options.regExp) identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`; - if(this.options.include) + if (this.options.include) identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`; - if(this.options.exclude) + if (this.options.exclude) identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`; - if(this.options.namespaceObject === "strict") + if (this.options.namespaceObject === "strict") identifier += " strict namespace object"; - else if(this.options.namespaceObject) - identifier += " namespace object"; + else if (this.options.namespaceObject) identifier += " namespace object"; return identifier; } libIdent(options) { let identifier = this.contextify(options.context, this.context); - if(this.options.mode) - identifier += ` ${this.options.mode}`; - if(this.options.recursive) - identifier += " recursive"; - if(this.options.addon) + if (this.options.mode) identifier += ` ${this.options.mode}`; + if (this.options.recursive) identifier += " recursive"; + if (this.options.addon) identifier += ` ${this.contextify(options.context, this.options.addon)}`; - if(this.options.regExp) + if (this.options.regExp) identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`; - if(this.options.include) + if (this.options.include) identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`; - if(this.options.exclude) + if (this.options.exclude) identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`; return identifier; @@ -131,7 +120,7 @@ class ContextModule extends Module { needRebuild(fileTimestamps, contextTimestamps) { const ts = contextTimestamps.get(this.context); - if(!ts) { + if (!ts) { return true; } @@ -146,65 +135,74 @@ class ContextModule extends Module { contextDependencies: this._contextDependencies }; this.resolveDependencies(fs, this.options, (err, dependencies) => { - if(err) return callback(err); + if (err) return callback(err); // abort if something failed // this will create an empty context - if(!dependencies) { + if (!dependencies) { callback(); return; } // enhance dependencies with meta info - for(const dep of dependencies) { + for (const dep of dependencies) { dep.loc = dep.userRequest; dep.request = this.options.addon + dep.request; } - if(this.options.mode === "sync" || this.options.mode === "eager") { - + if (this.options.mode === "sync" || this.options.mode === "eager") { // if we have an sync or eager context // just add all dependencies and continue this.dependencies = dependencies; - - } else if(this.options.mode === "lazy-once") { - + } else if (this.options.mode === "lazy-once") { // for the lazy-once mode create a new async dependency block // and add that block to this context - if(dependencies.length > 0) { - const block = new AsyncDependenciesBlock(this.options.chunkName, this); - for(const dep of dependencies) { + if (dependencies.length > 0) { + const block = new AsyncDependenciesBlock( + this.options.chunkName, + this + ); + for (const dep of dependencies) { block.addDependency(dep); } this.addBlock(block); } - - } else if(this.options.mode === "weak" || this.options.mode === "async-weak") { - + } else if ( + this.options.mode === "weak" || + this.options.mode === "async-weak" + ) { // we mark all dependencies as weak - for(const dep of dependencies) { + for (const dep of dependencies) { dep.weak = true; } this.dependencies = dependencies; - - } else if(this.options.mode === "lazy") { + } else if (this.options.mode === "lazy") { // if we are lazy create a new async dependency block per dependency // and add all blocks to this context let index = 0; - for(const dep of dependencies) { + for (const dep of dependencies) { let chunkName = this.options.chunkName; - if(chunkName) { - if(!/\[(index|request)\]/.test(chunkName)) - chunkName += "[index]"; + if (chunkName) { + if (!/\[(index|request)\]/.test(chunkName)) chunkName += "[index]"; chunkName = chunkName.replace(/\[index\]/g, index++); - chunkName = chunkName.replace(/\[request\]/g, Template.toPath(dep.userRequest)); + chunkName = chunkName.replace( + /\[request\]/g, + Template.toPath(dep.userRequest) + ); } - const block = new AsyncDependenciesBlock(chunkName, dep.module, dep.loc, dep.userRequest); + const block = new AsyncDependenciesBlock( + chunkName, + dep.module, + dep.loc, + dep.userRequest + ); block.addDependency(dep); this.addBlock(block); } } else { - callback(new Error(`Unsupported mode "${this.options.mode}" in context`)); + callback( + new Error(`Unsupported mode "${this.options.mode}" in context`) + ); return; } callback(); @@ -218,18 +216,19 @@ class ContextModule extends Module { return dependencies .filter(dependency => dependency.module) .sort((a, b) => { - if(a.userRequest === b.userRequest) { + if (a.userRequest === b.userRequest) { return 0; } return a.userRequest < b.userRequest ? -1 : 1; - }).reduce((map, dep) => { + }) + .reduce((map, dep) => { map[dep.userRequest] = dep.module.id; return map; }, Object.create(null)); } getFakeMap(dependencies) { - if(!this.options.namespaceObject) return 1; + if (!this.options.namespaceObject) return 1; // if we filter first we get a new array // therefor we dont need to create a clone of dependencies explicitly // therefore the order of this is !important! @@ -240,43 +239,52 @@ class ContextModule extends Module { .filter(dependency => dependency.module) .sort((a, b) => { return b.module.id - a.module.id; - }).reduce((map, dep) => { - const exportsType = dep.module.buildMeta && dep.module.buildMeta.exportsType; - if(!exportsType) hasNonHarmony = true; - if(exportsType === "namespace") hasNamespace = true; - if(exportsType === "named") hasNamed = true; - map[dep.module.id] = { - namespace: 1, - named: 2 - }[exportsType] || 0; + }) + .reduce((map, dep) => { + const exportsType = + dep.module.buildMeta && dep.module.buildMeta.exportsType; + if (!exportsType) hasNonHarmony = true; + if (exportsType === "namespace") hasNamespace = true; + if (exportsType === "named") hasNamed = true; + map[dep.module.id] = + { + namespace: 1, + named: 2 + }[exportsType] || 0; return map; }, Object.create(null)); - if(!hasNamespace && hasNonHarmony && !hasNamed) return 0; - if(hasNamespace && !hasNonHarmony && !hasNamed) return 1; - if(!hasNamespace && !hasNonHarmony && hasNamed) return 2; - if(!hasNamespace && !hasNonHarmony && !hasNamed) return 1; + if (!hasNamespace && hasNonHarmony && !hasNamed) return 0; + if (hasNamespace && !hasNonHarmony && !hasNamed) return 1; + if (!hasNamespace && !hasNonHarmony && hasNamed) return 2; + if (!hasNamespace && !hasNonHarmony && !hasNamed) return 1; return fakeMap; } getFakeMapInitStatement(fakeMap) { - return typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : ""; + return typeof fakeMap === "object" + ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` + : ""; } getReturn(type) { - if(type === 1) return "module"; - if(type === 2) return "Object.assign({/* fake namespace object */}, module, { \"default\": module })"; - if(type === 0) { - if(this.options.namespaceObject === "strict") { - return "/* fake namespace object */ { \"default\": module }"; + if (type === 1) return "module"; + if (type === 2) + return 'Object.assign({/* fake namespace object */}, module, { "default": module })'; + if (type === 0) { + if (this.options.namespaceObject === "strict") { + return '/* fake namespace object */ { "default": module }'; } else { - return "(typeof module === \"object\" && module && module.__esModule ? module : /* fake namespace object */ { \"default\": module })"; + return '(typeof module === "object" && module && module.__esModule ? module : /* fake namespace object */ { "default": module })'; } } } getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") { - if(typeof fakeMap === "number") return `return ${this.getReturn(fakeMap)};`; - return `return ${fakeMapDataExpression} === 1 ? ${this.getReturn(1)} : ${fakeMapDataExpression} ? ${this.getReturn(2)} : ${this.getReturn(0)};`; + if (typeof fakeMap === "number") + return `return ${this.getReturn(fakeMap)};`; + return `return ${fakeMapDataExpression} === 1 ? ${this.getReturn(1)} : ${ + fakeMapDataExpression + } ? ${this.getReturn(2)} : ${this.getReturn(0)};`; } getSyncSource(dependencies, id) { @@ -387,12 +395,13 @@ module.exports = webpackAsyncContext;`; getEagerSource(dependencies, id) { const map = this.getUserRequestMap(dependencies); const fakeMap = this.getFakeMap(dependencies); - const thenFunction = fakeMap !== 1 ? - `function(id) { + const thenFunction = + fakeMap !== 1 + ? `function(id) { var module = __webpack_require__(id); ${this.getReturnModuleObjectSource(fakeMap)} -}` : - "__webpack_require__"; +}` + : "__webpack_require__"; return `var map = ${JSON.stringify(map, null, "\t")}; ${this.getFakeMapInitStatement(fakeMap)} @@ -427,12 +436,13 @@ module.exports = webpackAsyncContext;`; }); const map = this.getUserRequestMap(dependencies); const fakeMap = this.getFakeMap(dependencies); - const thenFunction = fakeMap !== 1 ? - `function(id) { + const thenFunction = + fakeMap !== 1 + ? `function(id) { var module = __webpack_require__(id); ${this.getReturnModuleObjectSource(fakeMap)}; - }` : - "__webpack_require__"; + }` + : "__webpack_require__"; return `var map = ${JSON.stringify(map, null, "\t")}; ${this.getFakeMapInitStatement(fakeMap)} @@ -464,32 +474,41 @@ module.exports = webpackAsyncContext;`; const fakeMap = this.getFakeMap(blocks.map(b => b.dependencies[0])); const map = blocks .filter(block => block.dependencies[0].module) - .map((block) => ({ + .map(block => ({ dependency: block.dependencies[0], block: block, userRequest: block.dependencies[0].userRequest - })).sort((a, b) => { - if(a.userRequest === b.userRequest) return 0; + })) + .sort((a, b) => { + if (a.userRequest === b.userRequest) return 0; return a.userRequest < b.userRequest ? -1 : 1; - }).reduce((map, item) => { - const chunks = item.block.chunkGroup && item.block.chunkGroup.chunks || []; - if(chunks.length !== 1) { + }) + .reduce((map, item) => { + const chunks = + (item.block.chunkGroup && item.block.chunkGroup.chunks) || []; + if (chunks.length !== 1) { hasMultipleOrNoChunks = true; } const arrayStart = [item.dependency.module.id]; - if(typeof fakeMap === "object") + if (typeof fakeMap === "object") arrayStart.push(fakeMap[item.dependency.module.id]); - map[item.userRequest] = arrayStart - .concat(chunks.map(chunk => chunk.id)); + map[item.userRequest] = arrayStart.concat( + chunks.map(chunk => chunk.id) + ); return map; }, Object.create(null)); const chunksStartPosition = typeof fakeMap === "object" ? 2 : 1; - const requestPrefix = hasMultipleOrNoChunks ? - `Promise.all(ids.slice(${chunksStartPosition}).map(__webpack_require__.e))` : - `__webpack_require__.e(ids[${chunksStartPosition}])`; - const returnModuleObject = this.getReturnModuleObjectSource(fakeMap, "ids[1]"); + const requestPrefix = hasMultipleOrNoChunks + ? `Promise.all(ids.slice(${ + chunksStartPosition + }).map(__webpack_require__.e))` + : `__webpack_require__.e(ids[${chunksStartPosition}])`; + const returnModuleObject = this.getReturnModuleObjectSource( + fakeMap, + "ids[1]" + ); return `var map = ${JSON.stringify(map, null, "\t")}; function webpackAsyncContext(req) { @@ -542,44 +561,49 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`; } getSourceString(asyncMode, runtimeTemplate) { - if(asyncMode === "lazy") { - if(this.blocks && this.blocks.length > 0) { + if (asyncMode === "lazy") { + if (this.blocks && this.blocks.length > 0) { return this.getLazySource(this.blocks, this.id); } return this.getSourceForEmptyAsyncContext(this.id); } - if(asyncMode === "eager") { - if(this.dependencies && this.dependencies.length > 0) { + if (asyncMode === "eager") { + if (this.dependencies && this.dependencies.length > 0) { return this.getEagerSource(this.dependencies, this.id); } return this.getSourceForEmptyAsyncContext(this.id); } - if(asyncMode === "lazy-once") { + if (asyncMode === "lazy-once") { const block = this.blocks[0]; - if(block) { - return this.getLazyOnceSource(block, block.dependencies, this.id, runtimeTemplate); + if (block) { + return this.getLazyOnceSource( + block, + block.dependencies, + this.id, + runtimeTemplate + ); } return this.getSourceForEmptyAsyncContext(this.id); } - if(asyncMode === "async-weak") { - if(this.dependencies && this.dependencies.length > 0) { + if (asyncMode === "async-weak") { + if (this.dependencies && this.dependencies.length > 0) { return this.getAsyncWeakSource(this.dependencies, this.id); } return this.getSourceForEmptyAsyncContext(this.id); } - if(asyncMode === "weak") { - if(this.dependencies && this.dependencies.length > 0) { + if (asyncMode === "weak") { + if (this.dependencies && this.dependencies.length > 0) { return this.getWeakSyncSource(this.dependencies, this.id); } } - if(this.dependencies && this.dependencies.length > 0) { + if (this.dependencies && this.dependencies.length > 0) { return this.getSyncSource(this.dependencies, this.id); } return this.getSourceForEmptyContext(this.id); } getSource(sourceString) { - if(this.useSourceMap) { + if (this.useSourceMap) { return new OriginalSource(sourceString, this.identifier()); } return new RawSource(sourceString); @@ -596,8 +620,10 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`; const initialSize = 160; // if we dont have dependencies we stop here. - return this.dependencies - .reduce((size, dependency) => size + 5 + dependency.userRequest.length, initialSize); + return this.dependencies.reduce( + (size, dependency) => size + 5 + dependency.userRequest.length, + initialSize + ); } } diff --git a/lib/ContextModuleFactory.js b/lib/ContextModuleFactory.js index faadb758f..e11e2d0b7 100644 --- a/lib/ContextModuleFactory.js +++ b/lib/ContextModuleFactory.js @@ -25,7 +25,7 @@ module.exports = class ContextModuleFactory extends Tapable { alternatives: new AsyncSeriesWaterfallHook(["modules"]) }; this._pluginCompat.tap("ContextModuleFactory", options => { - switch(options.name) { + switch (options.name) { case "before-resolve": case "after-resolve": case "alternatives": @@ -41,72 +41,120 @@ module.exports = class ContextModuleFactory extends Tapable { const dependencies = data.dependencies; const resolveOptions = data.resolveOptions; const dependency = dependencies[0]; - this.hooks.beforeResolve.callAsync(Object.assign({ - context: context, - dependencies: dependencies, - resolveOptions - }, dependency.options), (err, beforeResolveResult) => { - if(err) return callback(err); - - // Ignored - if(!beforeResolveResult) return callback(); - - const context = beforeResolveResult.context; - const request = beforeResolveResult.request; - const resolveOptions = beforeResolveResult.resolveOptions; - - let loaders, resource, loadersPrefix = ""; - const idx = request.lastIndexOf("!"); - if(idx >= 0) { - loaders = request.substr(0, idx + 1); - let i; - for(i = 0; i < loaders.length && loaders[i] === "!"; i++) { - loadersPrefix += "!"; - } - loaders = loaders.substr(i).replace(/!+$/, "").replace(/!!+/g, "!"); - if(loaders === "") loaders = []; - else loaders = loaders.split("!"); - resource = request.substr(idx + 1); - } else { - loaders = []; - resource = request; - } - - const contextResolver = this.resolverFactory.get("context", resolveOptions || EMPTY_RESOLVE_OPTIONS); - const loaderResolver = this.resolverFactory.get("loader", EMPTY_RESOLVE_OPTIONS); - - asyncLib.parallel([ - callback => { - contextResolver.resolve({}, context, resource, {}, (err, result) => { - if(err) return callback(err); - callback(null, result); - }); + this.hooks.beforeResolve.callAsync( + Object.assign( + { + context: context, + dependencies: dependencies, + resolveOptions }, - callback => { - asyncLib.map(loaders, (loader, callback) => { - loaderResolver.resolve({}, context, loader, {}, (err, result) => { - if(err) return callback(err); - callback(null, result); - }); - }, callback); + dependency.options + ), + (err, beforeResolveResult) => { + if (err) return callback(err); + + // Ignored + if (!beforeResolveResult) return callback(); + + const context = beforeResolveResult.context; + const request = beforeResolveResult.request; + const resolveOptions = beforeResolveResult.resolveOptions; + + let loaders, + resource, + loadersPrefix = ""; + const idx = request.lastIndexOf("!"); + if (idx >= 0) { + loaders = request.substr(0, idx + 1); + let i; + for (i = 0; i < loaders.length && loaders[i] === "!"; i++) { + loadersPrefix += "!"; + } + loaders = loaders + .substr(i) + .replace(/!+$/, "") + .replace(/!!+/g, "!"); + if (loaders === "") loaders = []; + else loaders = loaders.split("!"); + resource = request.substr(idx + 1); + } else { + loaders = []; + resource = request; } - ], (err, result) => { - if(err) return callback(err); - this.hooks.afterResolve.callAsync(Object.assign({ - addon: loadersPrefix + result[1].join("!") + (result[1].length > 0 ? "!" : ""), - resource: result[0], - resolveDependencies: this.resolveDependencies.bind(this) - }, beforeResolveResult), (err, result) => { - if(err) return callback(err); + const contextResolver = this.resolverFactory.get( + "context", + resolveOptions || EMPTY_RESOLVE_OPTIONS + ); + const loaderResolver = this.resolverFactory.get( + "loader", + EMPTY_RESOLVE_OPTIONS + ); - // Ignored - if(!result) return callback(); + asyncLib.parallel( + [ + callback => { + contextResolver.resolve( + {}, + context, + resource, + {}, + (err, result) => { + if (err) return callback(err); + callback(null, result); + } + ); + }, + callback => { + asyncLib.map( + loaders, + (loader, callback) => { + loaderResolver.resolve( + {}, + context, + loader, + {}, + (err, result) => { + if (err) return callback(err); + callback(null, result); + } + ); + }, + callback + ); + } + ], + (err, result) => { + if (err) return callback(err); - return callback(null, new ContextModule(result.resolveDependencies, result)); - }); - }); - }); + this.hooks.afterResolve.callAsync( + Object.assign( + { + addon: + loadersPrefix + + result[1].join("!") + + (result[1].length > 0 ? "!" : ""), + resource: result[0], + resolveDependencies: this.resolveDependencies.bind(this) + }, + beforeResolveResult + ), + (err, result) => { + if (err) return callback(err); + + // Ignored + if (!result) return callback(); + + return callback( + null, + new ContextModule(result.resolveDependencies, result) + ); + } + ); + } + ); + } + ); } resolveDependencies(fs, options, callback) { @@ -117,63 +165,76 @@ module.exports = class ContextModuleFactory extends Tapable { let regExp = options.regExp; let include = options.include; let exclude = options.exclude; - if(!regExp || !resource) - return callback(null, []); + if (!regExp || !resource) return callback(null, []); const addDirectory = (directory, callback) => { fs.readdir(directory, (err, files) => { - if(err) return callback(err); + if (err) return callback(err); files = cmf.hooks.contextModuleFiles.call(files); - if(!files || files.length === 0) return callback(null, []); - asyncLib.map(files.filter(p => p.indexOf(".") !== 0), (seqment, callback) => { + if (!files || files.length === 0) return callback(null, []); + asyncLib.map( + files.filter(p => p.indexOf(".") !== 0), + (seqment, callback) => { + const subResource = path.join(directory, seqment); - const subResource = path.join(directory, seqment); - - if(!exclude || !subResource.match(exclude)) { - fs.stat(subResource, (err, stat) => { - if(err) { - if(err.code === "ENOENT") { - // ENOENT is ok here because the file may have been deleted between - // the readdir and stat calls. - return callback(); - } else { - return callback(err); + if (!exclude || !subResource.match(exclude)) { + fs.stat(subResource, (err, stat) => { + if (err) { + if (err.code === "ENOENT") { + // ENOENT is ok here because the file may have been deleted between + // the readdir and stat calls. + return callback(); + } else { + return callback(err); + } } - } - if(stat.isDirectory()) { + if (stat.isDirectory()) { + if (!recursive) return callback(); + addDirectory.call(this, subResource, callback); + } else if ( + stat.isFile() && + (!include || subResource.match(include)) + ) { + const obj = { + context: resource, + request: + "." + + subResource.substr(resource.length).replace(/\\/g, "/") + }; - if(!recursive) return callback(); - addDirectory.call(this, subResource, callback); + this.hooks.alternatives.callAsync( + [obj], + (err, alternatives) => { + if (err) return callback(err); + alternatives = alternatives + .filter(obj => regExp.test(obj.request)) + .map(obj => { + const dep = new ContextElementDependency( + obj.request + resourceQuery, + obj.request + ); + dep.optional = true; + return dep; + }); + callback(null, alternatives); + } + ); + } else callback(); + }); + } else callback(); + }, + (err, result) => { + if (err) return callback(err); - } else if(stat.isFile() && (!include || subResource.match(include))) { + if (!result) return callback(null, []); - const obj = { - context: resource, - request: "." + subResource.substr(resource.length).replace(/\\/g, "/") - }; - - this.hooks.alternatives.callAsync([obj], (err, alternatives) => { - if(err) return callback(err); - alternatives = alternatives.filter(obj => regExp.test(obj.request)).map(obj => { - const dep = new ContextElementDependency(obj.request + resourceQuery, obj.request); - dep.optional = true; - return dep; - }); - callback(null, alternatives); - }); - - } else callback(); - - }); - } else callback(); - }, (err, result) => { - if(err) return callback(err); - - if(!result) return callback(null, []); - - callback(null, result.filter(Boolean).reduce((a, i) => a.concat(i), [])); - }); + callback( + null, + result.filter(Boolean).reduce((a, i) => a.concat(i), []) + ); + } + ); }); }; diff --git a/lib/ContextReplacementPlugin.js b/lib/ContextReplacementPlugin.js index f6958fffe..84d1f0e74 100644 --- a/lib/ContextReplacementPlugin.js +++ b/lib/ContextReplacementPlugin.js @@ -8,26 +8,37 @@ const path = require("path"); const ContextElementDependency = require("./dependencies/ContextElementDependency"); class ContextReplacementPlugin { - constructor(resourceRegExp, newContentResource, newContentRecursive, newContentRegExp) { + constructor( + resourceRegExp, + newContentResource, + newContentRecursive, + newContentRegExp + ) { this.resourceRegExp = resourceRegExp; - if(typeof newContentResource === "function") { + if (typeof newContentResource === "function") { this.newContentCallback = newContentResource; - } else if(typeof newContentResource === "string" && typeof newContentRecursive === "object") { + } else if ( + typeof newContentResource === "string" && + typeof newContentRecursive === "object" + ) { this.newContentResource = newContentResource; this.newContentCreateContextMap = (fs, callback) => { callback(null, newContentRecursive); }; - } else if(typeof newContentResource === "string" && typeof newContentRecursive === "function") { + } else if ( + typeof newContentResource === "string" && + typeof newContentRecursive === "function" + ) { this.newContentResource = newContentResource; this.newContentCreateContextMap = newContentRecursive; } else { - if(typeof newContentResource !== "string") { + if (typeof newContentResource !== "string") { newContentRegExp = newContentRecursive; newContentRecursive = newContentResource; newContentResource = undefined; } - if(typeof newContentRecursive !== "boolean") { + if (typeof newContentRecursive !== "boolean") { newContentRegExp = newContentRecursive; newContentRecursive = undefined; } @@ -45,48 +56,48 @@ class ContextReplacementPlugin { const newContentRegExp = this.newContentRegExp; const newContentCreateContextMap = this.newContentCreateContextMap; - compiler.hooks.contextModuleFactory.tap("ContextReplacementPlugin", (cmf) => { - cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", (result) => { - if(!result) return; - if(resourceRegExp.test(result.request)) { - if(typeof newContentResource !== "undefined") + compiler.hooks.contextModuleFactory.tap("ContextReplacementPlugin", cmf => { + cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.request)) { + if (typeof newContentResource !== "undefined") result.request = newContentResource; - if(typeof newContentRecursive !== "undefined") + if (typeof newContentRecursive !== "undefined") result.recursive = newContentRecursive; - if(typeof newContentRegExp !== "undefined") + if (typeof newContentRegExp !== "undefined") result.regExp = newContentRegExp; - if(typeof newContentCallback === "function") { + if (typeof newContentCallback === "function") { newContentCallback(result); } else { - for(const d of result.dependencies) { - if(d.critical) - d.critical = false; + for (const d of result.dependencies) { + if (d.critical) d.critical = false; } } } return result; }); - cmf.hooks.afterResolve.tap("ContextReplacementPlugin", (result) => { - if(!result) return; - if(resourceRegExp.test(result.resource)) { - if(typeof newContentResource !== "undefined") + cmf.hooks.afterResolve.tap("ContextReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.resource)) { + if (typeof newContentResource !== "undefined") result.resource = path.resolve(result.resource, newContentResource); - if(typeof newContentRecursive !== "undefined") + if (typeof newContentRecursive !== "undefined") result.recursive = newContentRecursive; - if(typeof newContentRegExp !== "undefined") + if (typeof newContentRegExp !== "undefined") result.regExp = newContentRegExp; - if(typeof newContentCreateContextMap === "function") - result.resolveDependencies = createResolveDependenciesFromContextMap(newContentCreateContextMap); - if(typeof newContentCallback === "function") { + if (typeof newContentCreateContextMap === "function") + result.resolveDependencies = createResolveDependenciesFromContextMap( + newContentCreateContextMap + ); + if (typeof newContentCallback === "function") { const origResource = result.resource; newContentCallback(result); - if(result.resource !== origResource) { + if (result.resource !== origResource) { result.resource = path.resolve(origResource, result.resource); } } else { - for(const d of result.dependencies) { - if(d.critical) - d.critical = false; + for (const d of result.dependencies) { + if (d.critical) d.critical = false; } } } @@ -96,12 +107,15 @@ class ContextReplacementPlugin { } } -const createResolveDependenciesFromContextMap = (createContextMap) => { +const createResolveDependenciesFromContextMap = createContextMap => { const resolveDependenciesFromContextMap = (fs, options, callback) => { createContextMap(fs, (err, map) => { - if(err) return callback(err); - const dependencies = Object.keys(map).map((key) => { - return new ContextElementDependency(map[key] + options.resourceQuery, key); + if (err) return callback(err); + const dependencies = Object.keys(map).map(key => { + return new ContextElementDependency( + map[key] + options.resourceQuery, + key + ); }); callback(null, dependencies); }); diff --git a/lib/DefinePlugin.js b/lib/DefinePlugin.js index 408d496c5..ac3ffdba3 100644 --- a/lib/DefinePlugin.js +++ b/lib/DefinePlugin.js @@ -10,18 +10,25 @@ const ParserHelpers = require("./ParserHelpers"); const NullFactory = require("./NullFactory"); const stringifyObj = obj => { - return "Object({" + Object.keys(obj).map((key) => { - const code = obj[key]; - return JSON.stringify(key) + ":" + toCode(code); - }).join(",") + "})"; + return ( + "Object({" + + Object.keys(obj) + .map(key => { + const code = obj[key]; + return JSON.stringify(key) + ":" + toCode(code); + }) + .join(",") + + "})" + ); }; const toCode = code => { - if(code === null) return "null"; - else if(code === undefined) return "undefined"; - else if(code instanceof RegExp && code.toString) return code.toString(); - else if(typeof code === "function" && code.toString) return "(" + code.toString() + ")"; - else if(typeof code === "object") return stringifyObj(code); + if (code === null) return "null"; + else if (code === undefined) return "undefined"; + else if (code instanceof RegExp && code.toString) return code.toString(); + else if (typeof code === "function" && code.toString) + return "(" + code.toString() + ")"; + else if (typeof code === "object") return stringifyObj(code); else return code + ""; }; @@ -32,100 +39,159 @@ class DefinePlugin { apply(compiler) { const definitions = this.definitions; - compiler.hooks.compilation.tap("DefinePlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compiler.hooks.compilation.tap( + "DefinePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - const handler = (parser) => { - const walkDefinitions = (definitions, prefix) => { - Object.keys(definitions).forEach((key) => { - const code = definitions[key]; - if(code && typeof code === "object" && !(code instanceof RegExp)) { - walkDefinitions(code, prefix + key + "."); - applyObjectDefine(prefix + key, code); - return; + const handler = parser => { + const walkDefinitions = (definitions, prefix) => { + Object.keys(definitions).forEach(key => { + const code = definitions[key]; + if ( + code && + typeof code === "object" && + !(code instanceof RegExp) + ) { + walkDefinitions(code, prefix + key + "."); + applyObjectDefine(prefix + key, code); + return; + } + applyDefineKey(prefix, key); + applyDefine(prefix + key, code); + }); + }; + + const applyDefineKey = (prefix, key) => { + const splittedKey = key.split("."); + splittedKey.slice(1).forEach((_, i) => { + const fullKey = prefix + splittedKey.slice(0, i + 1).join("."); + parser.hooks.canRename + .for(fullKey) + .tap("DefinePlugin", ParserHelpers.approve); + }); + }; + + const applyDefine = (key, code) => { + const isTypeof = /^typeof\s+/.test(key); + if (isTypeof) key = key.replace(/^typeof\s+/, ""); + let recurse = false; + let recurseTypeof = false; + code = toCode(code); + if (!isTypeof) { + parser.hooks.canRename + .for(key) + .tap("DefinePlugin", ParserHelpers.approve); + parser.hooks.evaluateIdentifier + .for(key) + .tap("DefinePlugin", expr => { + /** + * this is needed in case there is a recursion in the DefinePlugin + * to prevent an endless recursion + * e.g.: new DefinePlugin({ + * "a": "b", + * "b": "a" + * }); + */ + if (recurse) return; + recurse = true; + const res = parser.evaluate(code); + recurse = false; + res.setRange(expr.range); + return res; + }); + parser.hooks.expression + .for(key) + .tap( + "DefinePlugin", + /__webpack_require__/.test(code) + ? ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + code + ) + : ParserHelpers.toConstantDependency(parser, code) + ); } - applyDefineKey(prefix, key); - applyDefine(prefix + key, code); - }); - }; - - const applyDefineKey = (prefix, key) => { - const splittedKey = key.split("."); - splittedKey.slice(1).forEach((_, i) => { - const fullKey = prefix + splittedKey.slice(0, i + 1).join("."); - parser.hooks.canRename.for(fullKey).tap("DefinePlugin", ParserHelpers.approve); - }); - }; - - const applyDefine = (key, code) => { - const isTypeof = /^typeof\s+/.test(key); - if(isTypeof) key = key.replace(/^typeof\s+/, ""); - let recurse = false; - let recurseTypeof = false; - code = toCode(code); - if(!isTypeof) { - parser.hooks.canRename.for(key).tap("DefinePlugin", ParserHelpers.approve); - parser.hooks.evaluateIdentifier.for(key).tap("DefinePlugin", (expr) => { + const typeofCode = isTypeof ? code : "typeof (" + code + ")"; + parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => { /** * this is needed in case there is a recursion in the DefinePlugin * to prevent an endless recursion * e.g.: new DefinePlugin({ - * "a": "b", - * "b": "a" + * "typeof a": "tyepof b", + * "typeof b": "typeof a" * }); */ - if(recurse) return; - recurse = true; - const res = parser.evaluate(code); - recurse = false; + if (recurseTypeof) return; + recurseTypeof = true; + const res = parser.evaluate(typeofCode); + recurseTypeof = false; res.setRange(expr.range); return res; }); - parser.hooks.expression.for(key).tap("DefinePlugin", /__webpack_require__/.test(code) ? ParserHelpers.toConstantDependencyWithWebpackRequire(parser, code) : ParserHelpers.toConstantDependency(parser, code)); - } - const typeofCode = isTypeof ? code : "typeof (" + code + ")"; - parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", (expr) => { - /** - * this is needed in case there is a recursion in the DefinePlugin - * to prevent an endless recursion - * e.g.: new DefinePlugin({ - * "typeof a": "tyepof b", - * "typeof b": "typeof a" - * }); - */ - if(recurseTypeof) return; - recurseTypeof = true; - const res = parser.evaluate(typeofCode); - recurseTypeof = false; - res.setRange(expr.range); - return res; - }); - parser.hooks.typeof.for(key).tap("DefinePlugin", (expr) => { - const res = parser.evaluate(typeofCode); - if(!res.isString()) return; - return ParserHelpers.toConstantDependency(parser, JSON.stringify(res.string)).bind(parser)(expr); - }); + parser.hooks.typeof.for(key).tap("DefinePlugin", expr => { + const res = parser.evaluate(typeofCode); + if (!res.isString()) return; + return ParserHelpers.toConstantDependency( + parser, + JSON.stringify(res.string) + ).bind(parser)(expr); + }); + }; + + const applyObjectDefine = (key, obj) => { + const code = stringifyObj(obj); + parser.hooks.canRename + .for(key) + .tap("DefinePlugin", ParserHelpers.approve); + parser.hooks.evaluateIdentifier + .for(key) + .tap("DefinePlugin", expr => + new BasicEvaluatedExpression().setTruthy().setRange(expr.range) + ); + parser.hooks.evaluateTypeof + .for(key) + .tap("DefinePlugin", ParserHelpers.evaluateToString("object")); + parser.hooks.expression + .for(key) + .tap( + "DefinePlugin", + /__webpack_require__/.test(code) + ? ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + code + ) + : ParserHelpers.toConstantDependency(parser, code) + ); + parser.hooks.typeof + .for(key) + .tap( + "DefinePlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("object") + ) + ); + }; + + walkDefinitions(definitions, ""); }; - const applyObjectDefine = (key, obj) => { - const code = stringifyObj(obj); - parser.hooks.canRename.for(key).tap("DefinePlugin", ParserHelpers.approve); - parser.hooks.evaluateIdentifier.for(key).tap("DefinePlugin", (expr) => new BasicEvaluatedExpression().setTruthy().setRange(expr.range)); - parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", ParserHelpers.evaluateToString("object")); - parser.hooks.expression.for(key).tap("DefinePlugin", /__webpack_require__/.test(code) ? ParserHelpers.toConstantDependencyWithWebpackRequire(parser, code) : ParserHelpers.toConstantDependency(parser, code)); - parser.hooks.typeof.for(key).tap("DefinePlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("object"))); - }; - - walkDefinitions(definitions, ""); - }; - - normalModuleFactory.hooks.parser.for("javascript/auto").tap("DefinePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("DefinePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("DefinePlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("DefinePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("DefinePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("DefinePlugin", handler); + } + ); } } module.exports = DefinePlugin; diff --git a/lib/DelegatedModule.js b/lib/DelegatedModule.js index 0ba3bf6fd..cd5fc0f81 100644 --- a/lib/DelegatedModule.js +++ b/lib/DelegatedModule.js @@ -25,11 +25,15 @@ class DelegatedModule extends Module { } libIdent(options) { - return typeof this.originalRequest === "string" ? this.originalRequest : this.originalRequest.libIdent(options); + return typeof this.originalRequest === "string" + ? this.originalRequest + : this.originalRequest.libIdent(options); } identifier() { - return `delegated ${JSON.stringify(this.request)} from ${this.sourceRequest}`; + return `delegated ${JSON.stringify(this.request)} from ${ + this.sourceRequest + }`; } readableIdentifier() { @@ -45,7 +49,9 @@ class DelegatedModule extends Module { this.buildMeta = Object.assign({}, this.delegateData.buildMeta); this.buildInfo = {}; this.addDependency(new DelegatedSourceDependency(this.sourceRequest)); - this.addDependency(new DelegatedExportsDependency(this, this.delegateData.exports || true)); + this.addDependency( + new DelegatedExportsDependency(this, this.delegateData.exports || true) + ); callback(); } @@ -54,7 +60,7 @@ class DelegatedModule extends Module { const sourceModule = dep.module; let str; - if(!sourceModule) { + if (!sourceModule) { str = WebpackMissingModule.moduleCode(this.sourceRequest); } else { str = `module.exports = (${runtime.moduleExports({ @@ -62,7 +68,7 @@ class DelegatedModule extends Module { request: dep.request })})`; - switch(this.type) { + switch (this.type) { case "require": str += `(${JSON.stringify(this.request)})`; break; @@ -74,7 +80,7 @@ class DelegatedModule extends Module { str += ";"; } - if(this.useSourceMap) { + if (this.useSourceMap) { return new OriginalSource(str, this.identifier()); } else { return new RawSource(str); diff --git a/lib/DelegatedModuleFactoryPlugin.js b/lib/DelegatedModuleFactoryPlugin.js index bd768e4d4..26db0066f 100644 --- a/lib/DelegatedModuleFactoryPlugin.js +++ b/lib/DelegatedModuleFactoryPlugin.js @@ -20,39 +20,69 @@ class DelegatedModuleFactoryPlugin { apply(normalModuleFactory) { const scope = this.options.scope; - if(scope) { - normalModuleFactory.hooks.factory.tap("DelegatedModuleFactoryPlugin", factory => (data, callback) => { - const dependency = data.dependencies[0]; - const request = dependency.request; - if(request && request.indexOf(scope + "/") === 0) { - const innerRequest = "." + request.substr(scope.length); - let resolved; - if(innerRequest in this.options.content) { - resolved = this.options.content[innerRequest]; - return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, innerRequest, request)); - } - for(let i = 0; i < this.options.extensions.length; i++) { - const extension = this.options.extensions[i]; - const requestPlusExt = innerRequest + extension; - if(requestPlusExt in this.options.content) { - resolved = this.options.content[requestPlusExt]; - return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, requestPlusExt, request + extension)); + if (scope) { + normalModuleFactory.hooks.factory.tap( + "DelegatedModuleFactoryPlugin", + factory => (data, callback) => { + const dependency = data.dependencies[0]; + const request = dependency.request; + if (request && request.indexOf(scope + "/") === 0) { + const innerRequest = "." + request.substr(scope.length); + let resolved; + if (innerRequest in this.options.content) { + resolved = this.options.content[innerRequest]; + return callback( + null, + new DelegatedModule( + this.options.source, + resolved, + this.options.type, + innerRequest, + request + ) + ); + } + for (let i = 0; i < this.options.extensions.length; i++) { + const extension = this.options.extensions[i]; + const requestPlusExt = innerRequest + extension; + if (requestPlusExt in this.options.content) { + resolved = this.options.content[requestPlusExt]; + return callback( + null, + new DelegatedModule( + this.options.source, + resolved, + this.options.type, + requestPlusExt, + request + extension + ) + ); + } } } + return factory(data, callback); } - return factory(data, callback); - }); + ); } else { - normalModuleFactory.hooks.module.tap("DelegatedModuleFactoryPlugin", module => { - if(module.libIdent) { - const request = module.libIdent(this.options); - if(request && request in this.options.content) { - const resolved = this.options.content[request]; - return new DelegatedModule(this.options.source, resolved, this.options.type, request, module); + normalModuleFactory.hooks.module.tap( + "DelegatedModuleFactoryPlugin", + module => { + if (module.libIdent) { + const request = module.libIdent(this.options); + if (request && request in this.options.content) { + const resolved = this.options.content[request]; + return new DelegatedModule( + this.options.source, + resolved, + this.options.type, + request, + module + ); + } } + return module; } - return module; - }); + ); } } } diff --git a/lib/DelegatedPlugin.js b/lib/DelegatedPlugin.js index 3fc146e10..714eb8533 100644 --- a/lib/DelegatedPlugin.js +++ b/lib/DelegatedPlugin.js @@ -16,16 +16,21 @@ class DelegatedPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("DelegatedPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory); - compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory()); - }); + compiler.hooks.compilation.tap( + "DelegatedPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + DelegatedSourceDependency, + normalModuleFactory + ); + compilation.dependencyFactories.set( + DelegatedExportsDependency, + new NullFactory() + ); + } + ); - compiler.hooks.compile.tap("DelegatedPlugin", ({ - normalModuleFactory - }) => { + compiler.hooks.compile.tap("DelegatedPlugin", ({ normalModuleFactory }) => { new DelegatedModuleFactoryPlugin(this.options).apply(normalModuleFactory); }); } diff --git a/lib/DependenciesBlock.js b/lib/DependenciesBlock.js index b9352a925..78a7d6f9d 100644 --- a/lib/DependenciesBlock.js +++ b/lib/DependenciesBlock.js @@ -19,12 +19,14 @@ class DependenciesBlock { } addVariable(name, expression, dependencies) { - for(let v of this.variables) { - if(v.name === name && v.expression === expression) { + for (let v of this.variables) { + if (v.name === name && v.expression === expression) { return; } } - this.variables.push(new DependenciesBlockVariable(name, expression, dependencies)); + this.variables.push( + new DependenciesBlockVariable(name, expression, dependencies) + ); } addDependency(dependency) { @@ -33,59 +35,47 @@ class DependenciesBlock { removeDependency(dependency) { const idx = this.dependencies.indexOf(dependency); - if(idx >= 0) - this.dependencies.splice(idx, 1); + if (idx >= 0) this.dependencies.splice(idx, 1); } updateHash(hash) { - for(const dep of this.dependencies) - dep.updateHash(hash); - for(const block of this.blocks) - block.updateHash(hash); - for(const variable of this.variables) - variable.updateHash(hash); + for (const dep of this.dependencies) dep.updateHash(hash); + for (const block of this.blocks) block.updateHash(hash); + for (const variable of this.variables) variable.updateHash(hash); } disconnect() { - for(const dep of this.dependencies) - dep.disconnect(); - for(const block of this.blocks) - block.disconnect(); - for(const variable of this.variables) - variable.disconnect(); + for (const dep of this.dependencies) dep.disconnect(); + for (const block of this.blocks) block.disconnect(); + for (const variable of this.variables) variable.disconnect(); } unseal() { - for(const block of this.blocks) - block.unseal(); + for (const block of this.blocks) block.unseal(); } hasDependencies(filter) { - if(filter) { - for(const dep of this.dependencies) { - if(filter(dep)) - return true; + if (filter) { + for (const dep of this.dependencies) { + if (filter(dep)) return true; } } else { - if(this.dependencies.length > 0) { + if (this.dependencies.length > 0) { return true; } } - for(const block of this.blocks) { - if(block.hasDependencies(filter)) - return true; + for (const block of this.blocks) { + if (block.hasDependencies(filter)) return true; } - for(const variable of this.variables) { - if(variable.hasDependencies(filter)) - return true; + for (const variable of this.variables) { + if (variable.hasDependencies(filter)) return true; } return false; } sortItems() { - for(const block of this.blocks) - block.sortItems(); + for (const block of this.blocks) block.sortItems(); } } diff --git a/lib/DependenciesBlockVariable.js b/lib/DependenciesBlockVariable.js index 4631f9e58..e26e56dfa 100644 --- a/lib/DependenciesBlockVariable.js +++ b/lib/DependenciesBlockVariable.js @@ -17,32 +17,33 @@ class DependenciesBlockVariable { updateHash(hash) { hash.update(this.name); hash.update(this.expression); - for(const d of this.dependencies) { + for (const d of this.dependencies) { d.updateHash(hash); } } expressionSource(dependencyTemplates, runtimeTemplate) { const source = new ReplaceSource(new RawSource(this.expression)); - for(const dep of this.dependencies) { + for (const dep of this.dependencies) { const template = dependencyTemplates.get(dep.constructor); - if(!template) throw new Error(`No template for dependency: ${dep.constructor.name}`); + if (!template) + throw new Error(`No template for dependency: ${dep.constructor.name}`); template.apply(dep, source, runtimeTemplate, dependencyTemplates); } return source; } disconnect() { - for(const d of this.dependencies) { + for (const d of this.dependencies) { d.disconnect(); } } hasDependencies(filter) { - if(filter) { - if(this.dependencies.some(filter)) return true; + if (filter) { + if (this.dependencies.some(filter)) return true; } else { - if(this.dependencies.length > 0) return true; + if (this.dependencies.length > 0) return true; } return false; } diff --git a/lib/Dependency.js b/lib/Dependency.js index 0cb59f380..0dbc0cae2 100644 --- a/lib/Dependency.js +++ b/lib/Dependency.js @@ -18,11 +18,11 @@ class Dependency { // Returns the referenced module and export getReference() { - if(!this.module) return null; + if (!this.module) return null; return { module: this.module, weak: this.weak, - importedNames: true, // true: full object, false: only sideeffects/no export, array of strings: the exports with this names + importedNames: true // true: full object, false: only sideeffects/no export, array of strings: the exports with this names }; } diff --git a/lib/DllEntryPlugin.js b/lib/DllEntryPlugin.js index 162771542..dbb1a40b3 100644 --- a/lib/DllEntryPlugin.js +++ b/lib/DllEntryPlugin.js @@ -16,19 +16,34 @@ class DllEntryPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("DllEntryPlugin", (compilation, { - normalModuleFactory - }) => { - const dllModuleFactory = new DllModuleFactory(); - compilation.dependencyFactories.set(DllEntryDependency, dllModuleFactory); - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); + compiler.hooks.compilation.tap( + "DllEntryPlugin", + (compilation, { normalModuleFactory }) => { + const dllModuleFactory = new DllModuleFactory(); + compilation.dependencyFactories.set( + DllEntryDependency, + dllModuleFactory + ); + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); compiler.hooks.make.tapAsync("DllEntryPlugin", (compilation, callback) => { - compilation.addEntry(this.context, new DllEntryDependency(this.entries.map((e, idx) => { - const dep = new SingleEntryDependency(e); - dep.loc = `${this.name}:${idx}`; - return dep; - }), this.name), this.name, callback); + compilation.addEntry( + this.context, + new DllEntryDependency( + this.entries.map((e, idx) => { + const dep = new SingleEntryDependency(e); + dep.loc = `${this.name}:${idx}`; + return dep; + }), + this.name + ), + this.name, + callback + ); }); } } diff --git a/lib/DllModuleFactory.js b/lib/DllModuleFactory.js index 990b4d281..f4339694a 100644 --- a/lib/DllModuleFactory.js +++ b/lib/DllModuleFactory.js @@ -14,7 +14,15 @@ class DllModuleFactory extends Tapable { } create(data, callback) { const dependency = data.dependencies[0]; - callback(null, new DllModule(data.context, dependency.dependencies, dependency.name, dependency.type)); + callback( + null, + new DllModule( + data.context, + dependency.dependencies, + dependency.name, + dependency.type + ) + ); } } diff --git a/lib/DllPlugin.js b/lib/DllPlugin.js index 7eeea5898..d56ade8d7 100644 --- a/lib/DllPlugin.js +++ b/lib/DllPlugin.js @@ -20,12 +20,10 @@ class DllPlugin { apply(compiler) { compiler.hooks.entryOption.tap("DllPlugin", (context, entry) => { const itemToPlugin = (item, name) => { - if(Array.isArray(item)) - return new DllEntryPlugin(context, item, name); - else - throw new Error("DllPlugin: supply an Array as entry"); + if (Array.isArray(item)) return new DllEntryPlugin(context, item, name); + else throw new Error("DllPlugin: supply an Array as entry"); }; - if(typeof entry === "object" && !Array.isArray(entry)) { + if (typeof entry === "object" && !Array.isArray(entry)) { Object.keys(entry).forEach(name => { itemToPlugin(entry[name], name).apply(compiler); }); diff --git a/lib/DllReferencePlugin.js b/lib/DllReferencePlugin.js index b141a3266..1bbb9d8a2 100644 --- a/lib/DllReferencePlugin.js +++ b/lib/DllReferencePlugin.js @@ -20,39 +20,54 @@ class DllReferencePlugin { } apply(compiler) { - compiler.hooks.compilation.tap("DllReferencePlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory); - compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory()); - }); - - compiler.hooks.beforeCompile.tapAsync("DllReferencePlugin", (params, callback) => { - const manifest = this.options.manifest; - if(typeof manifest === "string") { - params.compilationDependencies.add(manifest); - compiler.inputFileSystem.readFile(manifest, (err, result) => { - if(err) return callback(err); - params["dll reference " + manifest] = JSON.parse(result.toString("utf-8")); - return callback(); - }); - } else { - return callback(); + compiler.hooks.compilation.tap( + "DllReferencePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + DelegatedSourceDependency, + normalModuleFactory + ); + compilation.dependencyFactories.set( + DelegatedExportsDependency, + new NullFactory() + ); } - }); + ); - compiler.hooks.compile.tap("DllReferencePlugin", (params) => { + compiler.hooks.beforeCompile.tapAsync( + "DllReferencePlugin", + (params, callback) => { + const manifest = this.options.manifest; + if (typeof manifest === "string") { + params.compilationDependencies.add(manifest); + compiler.inputFileSystem.readFile(manifest, (err, result) => { + if (err) return callback(err); + params["dll reference " + manifest] = JSON.parse( + result.toString("utf-8") + ); + return callback(); + }); + } else { + return callback(); + } + } + ); + + compiler.hooks.compile.tap("DllReferencePlugin", params => { let manifest = this.options.manifest; - if(typeof manifest === "string") { + if (typeof manifest === "string") { manifest = params["dll reference " + manifest]; } const name = this.options.name || manifest.name; - const sourceType = this.options.sourceType || (manifest && manifest.type) || "var"; + const sourceType = + this.options.sourceType || (manifest && manifest.type) || "var"; const externals = {}; const source = "dll-reference " + name; externals[source] = name; const normalModuleFactory = params.normalModuleFactory; - new ExternalModuleFactoryPlugin(sourceType, externals).apply(normalModuleFactory); + new ExternalModuleFactoryPlugin(sourceType, externals).apply( + normalModuleFactory + ); new DelegatedModuleFactoryPlugin({ source: source, type: this.options.type, diff --git a/lib/DynamicEntryPlugin.js b/lib/DynamicEntryPlugin.js index 760a5f3f0..38a5dbb3f 100644 --- a/lib/DynamicEntryPlugin.js +++ b/lib/DynamicEntryPlugin.js @@ -17,44 +17,55 @@ class DynamicEntryPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("DynamicEntryPlugin", (compilation, { - normalModuleFactory - }) => { - const multiModuleFactory = new MultiModuleFactory(); + compiler.hooks.compilation.tap( + "DynamicEntryPlugin", + (compilation, { normalModuleFactory }) => { + const multiModuleFactory = new MultiModuleFactory(); - compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory); - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); + compilation.dependencyFactories.set( + MultiEntryDependency, + multiModuleFactory + ); + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); - compiler.hooks.make.tapAsync("DynamicEntryPlugin", (compilation, callback) => { - const addEntry = (entry, name) => { - const dep = DynamicEntryPlugin.createDependency(entry, name); - return new Promise((resolve, reject) => { - compilation.addEntry(this.context, dep, name, (err) => { - if(err) return reject(err); - resolve(); + compiler.hooks.make.tapAsync( + "DynamicEntryPlugin", + (compilation, callback) => { + const addEntry = (entry, name) => { + const dep = DynamicEntryPlugin.createDependency(entry, name); + return new Promise((resolve, reject) => { + compilation.addEntry(this.context, dep, name, err => { + if (err) return reject(err); + resolve(); + }); }); - }); - }; + }; - Promise.resolve(this.entry()).then((entry) => { - if(typeof entry === "string" || Array.isArray(entry)) { - addEntry(entry, "main").then(() => callback(), callback); - } else if(typeof entry === "object") { - Promise.all(Object.keys(entry).map((name) => { - return addEntry(entry[name], name); - })).then(() => callback(), callback); - } - }); - }); + Promise.resolve(this.entry()).then(entry => { + if (typeof entry === "string" || Array.isArray(entry)) { + addEntry(entry, "main").then(() => callback(), callback); + } else if (typeof entry === "object") { + Promise.all( + Object.keys(entry).map(name => { + return addEntry(entry[name], name); + }) + ).then(() => callback(), callback); + } + }); + } + ); } } module.exports = DynamicEntryPlugin; DynamicEntryPlugin.createDependency = (entry, name) => { - if(Array.isArray(entry)) + if (Array.isArray(entry)) return MultiEntryPlugin.createDependency(entry, name); - else - return SingleEntryPlugin.createDependency(entry, name); + else return SingleEntryPlugin.createDependency(entry, name); }; diff --git a/lib/EntryOptionPlugin.js b/lib/EntryOptionPlugin.js index e4525cfc3..c8c3ce755 100644 --- a/lib/EntryOptionPlugin.js +++ b/lib/EntryOptionPlugin.js @@ -9,7 +9,7 @@ const MultiEntryPlugin = require("./MultiEntryPlugin"); const DynamicEntryPlugin = require("./DynamicEntryPlugin"); const itemToPlugin = (context, item, name) => { - if(Array.isArray(item)) { + if (Array.isArray(item)) { return new MultiEntryPlugin(context, item, name); } return new SingleEntryPlugin(context, item, name); @@ -18,13 +18,13 @@ const itemToPlugin = (context, item, name) => { module.exports = class EntryOptionPlugin { apply(compiler) { compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => { - if(typeof entry === "string" || Array.isArray(entry)) { + if (typeof entry === "string" || Array.isArray(entry)) { itemToPlugin(context, entry, "main").apply(compiler); - } else if(typeof entry === "object") { - for(const name of Object.keys(entry)) { + } else if (typeof entry === "object") { + for (const name of Object.keys(entry)) { itemToPlugin(context, entry[name], name).apply(compiler); } - } else if(typeof entry === "function") { + } else if (typeof entry === "function") { new DynamicEntryPlugin(context, entry).apply(compiler); } return true; diff --git a/lib/Entrypoint.js b/lib/Entrypoint.js index 440d67c47..927a2cbd8 100644 --- a/lib/Entrypoint.js +++ b/lib/Entrypoint.js @@ -19,8 +19,8 @@ class Entrypoint extends ChunkGroup { getFiles() { const files = new Set(); - for(const chunk of this.chunks) { - for(const file of chunk.files) { + for (const chunk of this.chunks) { + for (const file of chunk.files) { files.add(file); } } diff --git a/lib/EnvironmentPlugin.js b/lib/EnvironmentPlugin.js index 7d48354d7..68da26ecf 100644 --- a/lib/EnvironmentPlugin.js +++ b/lib/EnvironmentPlugin.js @@ -7,15 +7,16 @@ const DefinePlugin = require("./DefinePlugin"); -const needsEnvVarFix = ["8", "9"].indexOf(process.versions.node.split(".")[0]) >= 0 && +const needsEnvVarFix = + ["8", "9"].indexOf(process.versions.node.split(".")[0]) >= 0 && process.platform === "win32"; class EnvironmentPlugin { constructor(...keys) { - if(keys.length === 1 && Array.isArray(keys[0])) { + if (keys.length === 1 && Array.isArray(keys[0])) { this.keys = keys[0]; this.defaultValues = {}; - } else if(keys.length === 1 && keys[0] && typeof keys[0] === "object") { + } else if (keys.length === 1 && keys[0] && typeof keys[0] === "object") { this.keys = Object.keys(keys[0]); this.defaultValues = keys[0]; } else { @@ -31,16 +32,21 @@ class EnvironmentPlugin { // affecting Node 8 & 9 by performing an OS-level // operation that always succeeds before reading // environment variables: - if(needsEnvVarFix) require("os").cpus(); + if (needsEnvVarFix) require("os").cpus(); - const value = process.env[key] !== undefined ? process.env[key] : this.defaultValues[key]; + const value = + process.env[key] !== undefined + ? process.env[key] + : this.defaultValues[key]; - if(value === undefined) { - compiler.hooks.thisCompilation.tap("EnvironmentPlugin", (compilation) => { + if (value === undefined) { + compiler.hooks.thisCompilation.tap("EnvironmentPlugin", compilation => { const error = new Error( - `EnvironmentPlugin - ${key} environment variable is undefined.\n\n` + - "You can pass an object with default values to suppress this warning.\n" + - "See https://webpack.js.org/plugins/environment-plugin for example." + `EnvironmentPlugin - ${ + key + } environment variable is undefined.\n\n` + + "You can pass an object with default values to suppress this warning.\n" + + "See https://webpack.js.org/plugins/environment-plugin for example." ); error.name = "EnvVariableNotDefinedError"; @@ -48,7 +54,8 @@ class EnvironmentPlugin { }); } - defs[`process.env.${key}`] = typeof value === "undefined" ? "undefined" : JSON.stringify(value); + defs[`process.env.${key}`] = + typeof value === "undefined" ? "undefined" : JSON.stringify(value); return defs; }, {}); diff --git a/lib/ErrorHelpers.js b/lib/ErrorHelpers.js index a6c8478e2..0c5029a8f 100644 --- a/lib/ErrorHelpers.js +++ b/lib/ErrorHelpers.js @@ -10,26 +10,33 @@ const webpackOptionsFlag = "WEBPACK_OPTIONS"; exports.cutOffByFlag = (stack, flag) => { stack = stack.split("\n"); - for(let i = 0; i < stack.length; i++) - if(stack[i].includes(flag)) - stack.length = i; + for (let i = 0; i < stack.length; i++) + if (stack[i].includes(flag)) stack.length = i; return stack.join("\n"); }; -exports.cutOffLoaderExecution = (stack) => exports.cutOffByFlag(stack, loaderFlag); +exports.cutOffLoaderExecution = stack => + exports.cutOffByFlag(stack, loaderFlag); -exports.cutOffWebpackOptinos = (stack) => exports.cutOffByFlag(stack, webpackOptionsFlag); +exports.cutOffWebpackOptinos = stack => + exports.cutOffByFlag(stack, webpackOptionsFlag); exports.cutOffMultilineMessage = (stack, message) => { stack = stack.split("\n"); message = message.split("\n"); - return stack.reduce((acc, line, idx) => line.includes(message[idx]) ? acc : acc.concat(line), []).join("\n"); + return stack + .reduce( + (acc, line, idx) => + line.includes(message[idx]) ? acc : acc.concat(line), + [] + ) + .join("\n"); }; exports.cutOffMessage = (stack, message) => { const nextLine = stack.indexOf("\n"); - if(nextLine === -1) { + if (nextLine === -1) { return stack === message ? "" : stack; } else { const firstLine = stack.substr(0, nextLine); diff --git a/lib/EvalDevToolModulePlugin.js b/lib/EvalDevToolModulePlugin.js index 7d71b256a..2af11f9c3 100644 --- a/lib/EvalDevToolModulePlugin.js +++ b/lib/EvalDevToolModulePlugin.js @@ -14,7 +14,7 @@ class EvalDevToolModulePlugin { } apply(compiler) { - compiler.hooks.compilation.tap("EvalDevToolModulePlugin", (compilation) => { + compiler.hooks.compilation.tap("EvalDevToolModulePlugin", compilation => { new EvalDevToolModuleTemplatePlugin({ sourceUrlComment: this.sourceUrlComment, moduleFilenameTemplate: this.moduleFilenameTemplate, diff --git a/lib/EvalDevToolModuleTemplatePlugin.js b/lib/EvalDevToolModuleTemplatePlugin.js index 1380a1738..c86b61a74 100644 --- a/lib/EvalDevToolModuleTemplatePlugin.js +++ b/lib/EvalDevToolModuleTemplatePlugin.js @@ -11,24 +11,45 @@ const cache = new WeakMap(); class EvalDevToolModuleTemplatePlugin { constructor(options) { this.sourceUrlComment = options.sourceUrlComment || "\n//# sourceURL=[url]"; - this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]?[loaders]"; + this.moduleFilenameTemplate = + options.moduleFilenameTemplate || + "webpack://[namespace]/[resourcePath]?[loaders]"; this.namespace = options.namespace || ""; } apply(moduleTemplate) { - moduleTemplate.hooks.module.tap("EvalDevToolModuleTemplatePlugin", (source, module) => { - const cacheEntry = cache.get(source); - if(cacheEntry !== undefined) return cacheEntry; - const content = source.source(); - const str = ModuleFilenameHelpers.createFilename(module, { - moduleFilenameTemplate: this.moduleFilenameTemplate, - namespace: this.namespace - }, moduleTemplate.runtimeTemplate.requestShortener); - const footer = "\n" + this.sourceUrlComment.replace(/\[url\]/g, encodeURI(str).replace(/%2F/g, "/").replace(/%20/g, "_").replace(/%5E/g, "^").replace(/%5C/g, "\\").replace(/^\//, "")); - const result = new RawSource(`eval(${JSON.stringify(content + footer)});`); - cache.set(source, result); - return result; - }); + moduleTemplate.hooks.module.tap( + "EvalDevToolModuleTemplatePlugin", + (source, module) => { + const cacheEntry = cache.get(source); + if (cacheEntry !== undefined) return cacheEntry; + const content = source.source(); + const str = ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: this.moduleFilenameTemplate, + namespace: this.namespace + }, + moduleTemplate.runtimeTemplate.requestShortener + ); + const footer = + "\n" + + this.sourceUrlComment.replace( + /\[url\]/g, + encodeURI(str) + .replace(/%2F/g, "/") + .replace(/%20/g, "_") + .replace(/%5E/g, "^") + .replace(/%5C/g, "\\") + .replace(/^\//, "") + ); + const result = new RawSource( + `eval(${JSON.stringify(content + footer)});` + ); + cache.set(source, result); + return result; + } + ); moduleTemplate.hooks.hash.tap("EvalDevToolModuleTemplatePlugin", hash => { hash.update("EvalDevToolModuleTemplatePlugin"); hash.update("2"); diff --git a/lib/EvalSourceMapDevToolModuleTemplatePlugin.js b/lib/EvalSourceMapDevToolModuleTemplatePlugin.js index 25d9bb897..4fffc5ef5 100644 --- a/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +++ b/lib/EvalSourceMapDevToolModuleTemplatePlugin.js @@ -10,8 +10,11 @@ const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); class EvalSourceMapDevToolModuleTemplatePlugin { constructor(compilation, options) { this.compilation = compilation; - this.sourceMapComment = options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; - this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resource-path]?[hash]"; + this.sourceMapComment = + options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; + this.moduleFilenameTemplate = + options.moduleFilenameTemplate || + "webpack://[namespace]/[resource-path]?[hash]"; this.namespace = options.namespace || ""; this.options = options; } @@ -19,61 +22,84 @@ class EvalSourceMapDevToolModuleTemplatePlugin { apply(moduleTemplate) { const self = this; const options = this.options; - const matchModule = ModuleFilenameHelpers.matchObject.bind(ModuleFilenameHelpers, options); - moduleTemplate.hooks.module.tap("EvalSourceMapDevToolModuleTemplatePlugin", (source, module) => { - if(source.__EvalSourceMapDevToolData) + const matchModule = ModuleFilenameHelpers.matchObject.bind( + ModuleFilenameHelpers, + options + ); + moduleTemplate.hooks.module.tap( + "EvalSourceMapDevToolModuleTemplatePlugin", + (source, module) => { + if (source.__EvalSourceMapDevToolData) + return source.__EvalSourceMapDevToolData; + if (!matchModule(module.resource)) { + return source; + } + + let sourceMap; + let content; + if (source.sourceAndMap) { + const sourceAndMap = source.sourceAndMap(options); + sourceMap = sourceAndMap.map; + content = sourceAndMap.source; + } else { + sourceMap = source.map(options); + content = source.source(); + } + if (!sourceMap) { + return source; + } + + // Clone (flat) the sourcemap to ensure that the mutations below do not persist. + sourceMap = Object.keys(sourceMap).reduce((obj, key) => { + obj[key] = sourceMap[key]; + return obj; + }, {}); + const modules = sourceMap.sources.map(source => { + const module = self.compilation.findModule(source); + return module || source; + }); + let moduleFilenames = modules.map(module => { + return ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: self.moduleFilenameTemplate, + namespace: self.namespace + }, + moduleTemplate.runtimeTemplate.requestShortener + ); + }); + moduleFilenames = ModuleFilenameHelpers.replaceDuplicates( + moduleFilenames, + (filename, i, n) => { + for (let j = 0; j < n; j++) filename += "*"; + return filename; + } + ); + sourceMap.sources = moduleFilenames; + sourceMap.sourceRoot = options.sourceRoot || ""; + sourceMap.file = `${module.id}.js`; + + const footer = + self.sourceMapComment.replace( + /\[url\]/g, + `data:application/json;charset=utf-8;base64,${Buffer.from( + JSON.stringify(sourceMap), + "utf8" + ).toString("base64")}` + ) + `\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug + source.__EvalSourceMapDevToolData = new RawSource( + `eval(${JSON.stringify(content + footer)});` + ); return source.__EvalSourceMapDevToolData; - if(!matchModule(module.resource)) { - return source; } - - let sourceMap; - let content; - if(source.sourceAndMap) { - const sourceAndMap = source.sourceAndMap(options); - sourceMap = sourceAndMap.map; - content = sourceAndMap.source; - } else { - sourceMap = source.map(options); - content = source.source(); + ); + moduleTemplate.hooks.hash.tap( + "EvalSourceMapDevToolModuleTemplatePlugin", + hash => { + hash.update("eval-source-map"); + hash.update("2"); } - if(!sourceMap) { - return source; - } - - // Clone (flat) the sourcemap to ensure that the mutations below do not persist. - sourceMap = Object.keys(sourceMap).reduce((obj, key) => { - obj[key] = sourceMap[key]; - return obj; - }, {}); - const modules = sourceMap.sources.map(source => { - const module = self.compilation.findModule(source); - return module || source; - }); - let moduleFilenames = modules.map(module => { - return ModuleFilenameHelpers.createFilename(module, { - moduleFilenameTemplate: self.moduleFilenameTemplate, - namespace: self.namespace - }, moduleTemplate.runtimeTemplate.requestShortener); - }); - moduleFilenames = ModuleFilenameHelpers.replaceDuplicates(moduleFilenames, (filename, i, n) => { - for(let j = 0; j < n; j++) - filename += "*"; - return filename; - }); - sourceMap.sources = moduleFilenames; - sourceMap.sourceRoot = options.sourceRoot || ""; - sourceMap.file = `${module.id}.js`; - - const footer = self.sourceMapComment.replace(/\[url\]/g, `data:application/json;charset=utf-8;base64,${Buffer.from(JSON.stringify(sourceMap), "utf8").toString("base64")}`) + - `\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug - source.__EvalSourceMapDevToolData = new RawSource(`eval(${JSON.stringify(content + footer)});`); - return source.__EvalSourceMapDevToolData; - }); - moduleTemplate.hooks.hash.tap("EvalSourceMapDevToolModuleTemplatePlugin", hash => { - hash.update("eval-source-map"); - hash.update("2"); - }); + ); } } module.exports = EvalSourceMapDevToolModuleTemplatePlugin; diff --git a/lib/EvalSourceMapDevToolPlugin.js b/lib/EvalSourceMapDevToolPlugin.js index 4eafd27f0..a4641209b 100644 --- a/lib/EvalSourceMapDevToolPlugin.js +++ b/lib/EvalSourceMapDevToolPlugin.js @@ -9,23 +9,31 @@ const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOpt class EvalSourceMapDevToolPlugin { constructor(options) { - if(arguments.length > 1) - throw new Error("EvalSourceMapDevToolPlugin only takes one argument (pass an options object)"); - if(typeof options === "string") { + if (arguments.length > 1) + throw new Error( + "EvalSourceMapDevToolPlugin only takes one argument (pass an options object)" + ); + if (typeof options === "string") { options = { append: options }; } - if(!options) options = {}; + if (!options) options = {}; this.options = options; } apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("EvalSourceMapDevToolPlugin", (compilation) => { - new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); - new EvalSourceMapDevToolModuleTemplatePlugin(compilation, options).apply(compilation.moduleTemplates.javascript); - }); + compiler.hooks.compilation.tap( + "EvalSourceMapDevToolPlugin", + compilation => { + new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); + new EvalSourceMapDevToolModuleTemplatePlugin( + compilation, + options + ).apply(compilation.moduleTemplates.javascript); + } + ); } } diff --git a/lib/ExportPropertyMainTemplatePlugin.js b/lib/ExportPropertyMainTemplatePlugin.js index deed51db4..f8ef522ea 100644 --- a/lib/ExportPropertyMainTemplatePlugin.js +++ b/lib/ExportPropertyMainTemplatePlugin.js @@ -16,18 +16,18 @@ class ExportPropertyMainTemplatePlugin { } apply(compilation) { - const { - mainTemplate, - chunkTemplate - } = compilation; + const { mainTemplate, chunkTemplate } = compilation; const onRenderWithEntry = (source, chunk, hash) => { const postfix = `${accessorToObjectAccess([].concat(this.property))}`; return new ConcatSource(source, postfix); }; - for(const template of [mainTemplate, chunkTemplate]) { - template.hooks.renderWithEntry.tap("ExportPropertyMainTemplatePlugin", onRenderWithEntry); + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "ExportPropertyMainTemplatePlugin", + onRenderWithEntry + ); } mainTemplate.hooks.hash.tap("ExportPropertyMainTemplatePlugin", hash => { diff --git a/lib/ExtendedAPIPlugin.js b/lib/ExtendedAPIPlugin.js index 3851ee5e0..a894a9faf 100644 --- a/lib/ExtendedAPIPlugin.js +++ b/lib/ExtendedAPIPlugin.js @@ -20,36 +20,64 @@ const REPLACEMENT_TYPES = { class ExtendedAPIPlugin { apply(compiler) { - compiler.hooks.compilation.tap("ExtendedAPIPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compiler.hooks.compilation.tap( + "ExtendedAPIPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - const mainTemplate = compilation.mainTemplate; - mainTemplate.hooks.requireExtensions.tap("ExtendedAPIPlugin", (source, chunk, hash) => { - const buf = [source]; - buf.push(""); - buf.push("// __webpack_hash__"); - buf.push(`${mainTemplate.requireFn}.h = ${JSON.stringify(hash)};`); - buf.push(""); - buf.push("// __webpack_chunkname__"); - buf.push(`${mainTemplate.requireFn}.cn = ${JSON.stringify(chunk.name)};`); - return Template.asString(buf); - }); - mainTemplate.hooks.globalHash.tap("ExtendedAPIPlugin", () => true); + const mainTemplate = compilation.mainTemplate; + mainTemplate.hooks.requireExtensions.tap( + "ExtendedAPIPlugin", + (source, chunk, hash) => { + const buf = [source]; + buf.push(""); + buf.push("// __webpack_hash__"); + buf.push(`${mainTemplate.requireFn}.h = ${JSON.stringify(hash)};`); + buf.push(""); + buf.push("// __webpack_chunkname__"); + buf.push( + `${mainTemplate.requireFn}.cn = ${JSON.stringify(chunk.name)};` + ); + return Template.asString(buf); + } + ); + mainTemplate.hooks.globalHash.tap("ExtendedAPIPlugin", () => true); - const handler = (parser, parserOptions) => { - Object.keys(REPLACEMENTS).forEach(key => { - parser.hooks.expression.for(key).tap("ExtendedAPIPlugin", ParserHelpers.toConstantDependencyWithWebpackRequire(parser, REPLACEMENTS[key])); - parser.hooks.evaluateTypeof.for(key).tap("ExtendedAPIPlugin", ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])); - }); - }; + const handler = (parser, parserOptions) => { + Object.keys(REPLACEMENTS).forEach(key => { + parser.hooks.expression + .for(key) + .tap( + "ExtendedAPIPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + REPLACEMENTS[key] + ) + ); + parser.hooks.evaluateTypeof + .for(key) + .tap( + "ExtendedAPIPlugin", + ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key]) + ); + }); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("ExtendedAPIPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ExtendedAPIPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("ExtendedAPIPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ExtendedAPIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ExtendedAPIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ExtendedAPIPlugin", handler); + } + ); } } diff --git a/lib/ExternalModule.js b/lib/ExternalModule.js index 048291370..6a0b16799 100644 --- a/lib/ExternalModule.js +++ b/lib/ExternalModule.js @@ -48,64 +48,92 @@ class ExternalModule extends Module { } getSourceForGlobalVariableExternal(variableName, type) { - if(!Array.isArray(variableName)) { + if (!Array.isArray(variableName)) { // make it an array as the look up works the same basically variableName = [variableName]; } // needed for e.g. window["some"]["thing"] - const objectLookup = variableName.map(r => `[${JSON.stringify(r)}]`).join(""); + const objectLookup = variableName + .map(r => `[${JSON.stringify(r)}]`) + .join(""); return `(function() { module.exports = ${type}${objectLookup}; }());`; } getSourceForCommonJsExternal(moduleAndSpecifiers) { - if(!Array.isArray(moduleAndSpecifiers)) { - return `module.exports = require(${JSON.stringify(moduleAndSpecifiers)});`; + if (!Array.isArray(moduleAndSpecifiers)) { + return `module.exports = require(${JSON.stringify( + moduleAndSpecifiers + )});`; } const moduleName = moduleAndSpecifiers[0]; - const objectLookup = moduleAndSpecifiers.slice(1).map(r => `[${JSON.stringify(r)}]`).join(""); + const objectLookup = moduleAndSpecifiers + .slice(1) + .map(r => `[${JSON.stringify(r)}]`) + .join(""); return `module.exports = require(${moduleName})${objectLookup};`; } checkExternalVariable(variableToCheck, request) { - return `if(typeof ${variableToCheck} === 'undefined') {${WebpackMissingModule.moduleCode(request)}}\n`; + return `if(typeof ${ + variableToCheck + } === 'undefined') {${WebpackMissingModule.moduleCode(request)}}\n`; } getSourceForAmdOrUmdExternal(id, optional, request) { - const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${id}`)}__`; - const missingModuleError = optional ? this.checkExternalVariable(externalVariable, request) : ""; + const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier( + `${id}` + )}__`; + const missingModuleError = optional + ? this.checkExternalVariable(externalVariable, request) + : ""; return `${missingModuleError}module.exports = ${externalVariable};`; } getSourceForDefaultCase(optional, request) { - const missingModuleError = optional ? this.checkExternalVariable(request, request) : ""; + const missingModuleError = optional + ? this.checkExternalVariable(request, request) + : ""; return `${missingModuleError}module.exports = ${request};`; } getSourceString(runtime) { - const request = typeof this.request === "object" ? this.request[this.externalType] : this.request; - switch(this.externalType) { + const request = + typeof this.request === "object" + ? this.request[this.externalType] + : this.request; + switch (this.externalType) { case "this": case "window": case "self": - return this.getSourceForGlobalVariableExternal(request, this.externalType); + return this.getSourceForGlobalVariableExternal( + request, + this.externalType + ); case "global": - return this.getSourceForGlobalVariableExternal(runtime.outputOptions.globalObject, this.externalType); + return this.getSourceForGlobalVariableExternal( + runtime.outputOptions.globalObject, + this.externalType + ); case "commonjs": case "commonjs2": return this.getSourceForCommonJsExternal(request); case "amd": case "umd": case "umd2": - return this.getSourceForAmdOrUmdExternal(this.id, this.optional, request); + return this.getSourceForAmdOrUmdExternal( + this.id, + this.optional, + request + ); default: return this.getSourceForDefaultCase(this.optional, request); } } getSource(sourceString) { - if(this.useSourceMap) { + if (this.useSourceMap) { return new OriginalSource(sourceString, this.identifier()); } @@ -113,9 +141,7 @@ class ExternalModule extends Module { } source(dependencyTemplates, runtime) { - return this.getSource( - this.getSourceString(runtime) - ); + return this.getSource(this.getSourceString(runtime)); } size() { diff --git a/lib/ExternalModuleFactoryPlugin.js b/lib/ExternalModuleFactoryPlugin.js index 74e2ae51a..40c215660 100644 --- a/lib/ExternalModuleFactoryPlugin.js +++ b/lib/ExternalModuleFactoryPlugin.js @@ -14,83 +14,97 @@ class ExternalModuleFactoryPlugin { apply(normalModuleFactory) { const globalType = this.type; - normalModuleFactory.hooks.factory.tap("ExternalModuleFactoryPlugin", factory => (data, callback) => { - const context = data.context; - const dependency = data.dependencies[0]; + normalModuleFactory.hooks.factory.tap( + "ExternalModuleFactoryPlugin", + factory => (data, callback) => { + const context = data.context; + const dependency = data.dependencies[0]; - const handleExternal = (value, type, callback) => { - if(typeof type === "function") { - callback = type; - type = undefined; - } - if(value === false) return factory(data, callback); - if(value === true) value = dependency.request; - if(typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) { - const idx = value.indexOf(" "); - type = value.substr(0, idx); - value = value.substr(idx + 1); - } - callback(null, new ExternalModule(value, type || globalType, dependency.request)); - return true; - }; - - const handleExternals = (externals, callback) => { - if(typeof externals === "string") { - if(externals === dependency.request) { - return handleExternal(dependency.request, callback); + const handleExternal = (value, type, callback) => { + if (typeof type === "function") { + callback = type; + type = undefined; } - } else if(Array.isArray(externals)) { - let i = 0; - const next = () => { - let asyncFlag; - const handleExternalsAndCallback = (err, module) => { - if(err) return callback(err); - if(!module) { - if(asyncFlag) { - asyncFlag = false; - return; + if (value === false) return factory(data, callback); + if (value === true) value = dependency.request; + if (typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) { + const idx = value.indexOf(" "); + type = value.substr(0, idx); + value = value.substr(idx + 1); + } + callback( + null, + new ExternalModule(value, type || globalType, dependency.request) + ); + return true; + }; + + const handleExternals = (externals, callback) => { + if (typeof externals === "string") { + if (externals === dependency.request) { + return handleExternal(dependency.request, callback); + } + } else if (Array.isArray(externals)) { + let i = 0; + const next = () => { + let asyncFlag; + const handleExternalsAndCallback = (err, module) => { + if (err) return callback(err); + if (!module) { + if (asyncFlag) { + asyncFlag = false; + return; + } + return next(); } - return next(); - } - callback(null, module); + callback(null, module); + }; + + do { + asyncFlag = true; + if (i >= externals.length) return callback(); + handleExternals(externals[i++], handleExternalsAndCallback); + } while (!asyncFlag); // eslint-disable-line keyword-spacing + asyncFlag = false; }; - do { - asyncFlag = true; - if(i >= externals.length) return callback(); - handleExternals(externals[i++], handleExternalsAndCallback); - } while (!asyncFlag); // eslint-disable-line keyword-spacing - asyncFlag = false; - }; - - next(); - return; - } else if(externals instanceof RegExp) { - if(externals.test(dependency.request)) { - return handleExternal(dependency.request, callback); - } - } else if(typeof externals === "function") { - externals.call(null, context, dependency.request, (err, value, type) => { - if(err) return callback(err); - if(typeof value !== "undefined") { - handleExternal(value, type, callback); - } else { - callback(); + next(); + return; + } else if (externals instanceof RegExp) { + if (externals.test(dependency.request)) { + return handleExternal(dependency.request, callback); } - }); - return; - } else if(typeof externals === "object" && Object.prototype.hasOwnProperty.call(externals, dependency.request)) { - return handleExternal(externals[dependency.request], callback); - } - callback(); - }; + } else if (typeof externals === "function") { + externals.call( + null, + context, + dependency.request, + (err, value, type) => { + if (err) return callback(err); + if (typeof value !== "undefined") { + handleExternal(value, type, callback); + } else { + callback(); + } + } + ); + return; + } else if ( + typeof externals === "object" && + Object.prototype.hasOwnProperty.call(externals, dependency.request) + ) { + return handleExternal(externals[dependency.request], callback); + } + callback(); + }; - handleExternals(this.externals, (err, module) => { - if(err) return callback(err); - if(!module) return handleExternal(false, callback); - return callback(null, module); - }); - }); + handleExternals(this.externals, (err, module) => { + if (err) return callback(err); + if (!module) return handleExternal(false, callback); + return callback(null, module); + }); + } + ); } } module.exports = ExternalModuleFactoryPlugin; diff --git a/lib/ExternalsPlugin.js b/lib/ExternalsPlugin.js index 72f8d4943..697f1aaa0 100644 --- a/lib/ExternalsPlugin.js +++ b/lib/ExternalsPlugin.js @@ -12,10 +12,10 @@ class ExternalsPlugin { this.externals = externals; } apply(compiler) { - compiler.hooks.compile.tap("ExternalsPlugin", ({ - normalModuleFactory - }) => { - new ExternalModuleFactoryPlugin(this.type, this.externals).apply(normalModuleFactory); + compiler.hooks.compile.tap("ExternalsPlugin", ({ normalModuleFactory }) => { + new ExternalModuleFactoryPlugin(this.type, this.externals).apply( + normalModuleFactory + ); }); } } diff --git a/lib/FlagDependencyExportsPlugin.js b/lib/FlagDependencyExportsPlugin.js index b37089f5d..0aafb0b4a 100644 --- a/lib/FlagDependencyExportsPlugin.js +++ b/lib/FlagDependencyExportsPlugin.js @@ -8,8 +8,8 @@ const Queue = require("./util/Queue"); const addToSet = (a, b) => { let changed = false; - for(const item of b) { - if(!a.has(item)) { + for (const item of b) { + if (!a.has(item)) { a.add(item); changed = true; } @@ -18,113 +18,128 @@ const addToSet = (a, b) => { }; class FlagDependencyExportsPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("FlagDependencyExportsPlugin", (compilation) => { - compilation.hooks.finishModules.tap("FlagDependencyExportsPlugin", (modules) => { - const dependencies = new Map(); + compiler.hooks.compilation.tap( + "FlagDependencyExportsPlugin", + compilation => { + compilation.hooks.finishModules.tap( + "FlagDependencyExportsPlugin", + modules => { + const dependencies = new Map(); - const queue = new Queue(); + const queue = new Queue(); - let module; - let moduleWithExports; - let moduleProvidedExports; + let module; + let moduleWithExports; + let moduleProvidedExports; - const processDependenciesBlock = depBlock => { - for(const dep of depBlock.dependencies) { - if(processDependency(dep)) - return true; - } - for(const variable of depBlock.variables) { - for(const dep of variable.dependencies) { - if(processDependency(dep)) + const processDependenciesBlock = depBlock => { + for (const dep of depBlock.dependencies) { + if (processDependency(dep)) return true; + } + for (const variable of depBlock.variables) { + for (const dep of variable.dependencies) { + if (processDependency(dep)) return true; + } + } + for (const block of depBlock.blocks) { + if (processDependenciesBlock(block)) return true; + } + return false; + }; + + const processDependency = dep => { + const exportDesc = dep.getExports && dep.getExports(); + if (!exportDesc) return; + moduleWithExports = true; + const exports = exportDesc.exports; + // break early if it's only in the worst state + if (module.buildMeta.providedExports === true) { return true; - } - } - for(const block of depBlock.blocks) { - if(processDependenciesBlock(block)) - return true; - } - return false; - }; + } + // break if it should move to the worst state + if (exports === true) { + module.buildMeta.providedExports = true; + notifyDependencies(); + return true; + } + // merge in new exports + if (Array.isArray(exports)) { + if (addToSet(moduleProvidedExports, exports)) { + notifyDependencies(); + } + } + // store dependencies + const exportDeps = exportDesc.dependencies; + if (exportDeps) { + for (const exportDependency of exportDeps) { + // add dependency for this module + const set = dependencies.get(exportDependency); + if (set === undefined) { + dependencies.set(exportDependency, new Set([module])); + } else { + set.add(module); + } + } + } + return false; + }; - const processDependency = dep => { - const exportDesc = dep.getExports && dep.getExports(); - if(!exportDesc) return; - moduleWithExports = true; - const exports = exportDesc.exports; - // break early if it's only in the worst state - if(module.buildMeta.providedExports === true) { - return true; - } - // break if it should move to the worst state - if(exports === true) { - module.buildMeta.providedExports = true; - notifyDependencies(); - return true; - } - // merge in new exports - if(Array.isArray(exports)) { - if(addToSet(moduleProvidedExports, exports)) { - notifyDependencies(); + const notifyDependencies = () => { + const deps = dependencies.get(module); + if (deps !== undefined) { + for (const dep of deps) { + queue.enqueue(dep); + } + } + }; + + // Start with all modules without provided exports + for (const module of modules) { + if (!module.buildMeta.providedExports) { + queue.enqueue(module); + } } - } - // store dependencies - const exportDeps = exportDesc.dependencies; - if(exportDeps) { - for(const exportDependency of exportDeps) { - // add dependency for this module - const set = dependencies.get(exportDependency); - if(set === undefined) { - dependencies.set(exportDependency, new Set([module])); - } else { - set.add(module); + + while (queue.length > 0) { + module = queue.dequeue(); + + if (module.buildMeta.providedExports !== true) { + moduleWithExports = + module.buildMeta && module.buildMeta.exportsType; + moduleProvidedExports = Array.isArray( + module.buildMeta.providedExports + ) + ? new Set(module.buildMeta.providedExports) + : new Set(); + processDependenciesBlock(module); + if (!moduleWithExports) { + module.buildMeta.providedExports = true; + notifyDependencies(); + } else if (module.buildMeta.providedExports !== true) { + module.buildMeta.providedExports = Array.from( + moduleProvidedExports + ); + } } } } - return false; - }; - - const notifyDependencies = () => { - const deps = dependencies.get(module); - if(deps !== undefined) { - for(const dep of deps) { - queue.enqueue(dep); - } + ); + const providedExportsCache = new WeakMap(); + compilation.hooks.rebuildModule.tap( + "FlagDependencyExportsPlugin", + module => { + providedExportsCache.set(module, module.buildMeta.providedExports); } - }; - - // Start with all modules without provided exports - for(const module of modules) { - if(!module.buildMeta.providedExports) { - queue.enqueue(module); + ); + compilation.hooks.finishRebuildingModule.tap( + "FlagDependencyExportsPlugin", + module => { + module.buildMeta.providedExports = providedExportsCache.get(module); } - } - - while(queue.length > 0) { - module = queue.dequeue(); - - if(module.buildMeta.providedExports !== true) { - moduleWithExports = module.buildMeta && module.buildMeta.exportsType; - moduleProvidedExports = Array.isArray(module.buildMeta.providedExports) ? new Set(module.buildMeta.providedExports) : new Set(); - processDependenciesBlock(module); - if(!moduleWithExports) { - module.buildMeta.providedExports = true; - notifyDependencies(); - } else if(module.buildMeta.providedExports !== true) { - module.buildMeta.providedExports = Array.from(moduleProvidedExports); - } - } - } - }); - const providedExportsCache = new WeakMap(); - compilation.hooks.rebuildModule.tap("FlagDependencyExportsPlugin", module => { - providedExportsCache.set(module, module.buildMeta.providedExports); - }); - compilation.hooks.finishRebuildingModule.tap("FlagDependencyExportsPlugin", module => { - module.buildMeta.providedExports = providedExportsCache.get(module); - }); - }); + ); + } + ); } } diff --git a/lib/FlagDependencyUsagePlugin.js b/lib/FlagDependencyUsagePlugin.js index 86a6249cd..42dd4c0e2 100644 --- a/lib/FlagDependencyUsagePlugin.js +++ b/lib/FlagDependencyUsagePlugin.js @@ -5,92 +5,99 @@ "use strict"; const addToSet = (a, b) => { - for(const item of b) { - if(!a.includes(item)) - a.push(item); + for (const item of b) { + if (!a.includes(item)) a.push(item); } return a; }; const isSubset = (biggerSet, subset) => { - if(biggerSet === true) return true; - if(subset === true) return false; + if (biggerSet === true) return true; + if (subset === true) return false; return subset.every(item => biggerSet.indexOf(item) >= 0); }; class FlagDependencyUsagePlugin { apply(compiler) { - compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", (compilation) => { - compilation.hooks.optimizeModulesAdvanced.tap("FlagDependencyUsagePlugin", (modules) => { + compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => { + compilation.hooks.optimizeModulesAdvanced.tap( + "FlagDependencyUsagePlugin", + modules => { + const processModule = (module, usedExports) => { + module.used = true; + if (module.usedExports === true) return; + else if (usedExports === true) module.usedExports = true; + else if (Array.isArray(usedExports)) { + const old = module.usedExports ? module.usedExports.length : -1; + module.usedExports = addToSet( + module.usedExports || [], + usedExports + ); + if (module.usedExports.length === old) return; + } else if (Array.isArray(module.usedExports)) return; + else module.usedExports = false; - const processModule = (module, usedExports) => { - module.used = true; - if(module.usedExports === true) - return; - else if(usedExports === true) - module.usedExports = true; - else if(Array.isArray(usedExports)) { - const old = module.usedExports ? module.usedExports.length : -1; - module.usedExports = addToSet(module.usedExports || [], usedExports); - if(module.usedExports.length === old) - return; - } else if(Array.isArray(module.usedExports)) - return; - else - module.usedExports = false; + // for a module without side effects we stop tracking usage here when no export is used + // This module won't be evaluated in this case + if (module.factoryMeta.sideEffectFree) { + if (module.usedExports === false) return; + if ( + Array.isArray(module.usedExports) && + module.usedExports.length === 0 + ) + return; + } - // for a module without side effects we stop tracking usage here when no export is used - // This module won't be evaluated in this case - if(module.factoryMeta.sideEffectFree) { - if(module.usedExports === false) return; - if(Array.isArray(module.usedExports) && module.usedExports.length === 0) return; - } + queue.push([module, module.usedExports]); + }; - queue.push([module, module.usedExports]); - }; - - const processDependenciesBlock = (depBlock, usedExports) => { - for(const dep of depBlock.dependencies) { - processDependency(dep); - } - for(const variable of depBlock.variables) { - for(const dep of variable.dependencies) { + const processDependenciesBlock = (depBlock, usedExports) => { + for (const dep of depBlock.dependencies) { processDependency(dep); } - } - for(const block of depBlock.blocks) { - queue.push([block, usedExports]); - } - }; + for (const variable of depBlock.variables) { + for (const dep of variable.dependencies) { + processDependency(dep); + } + } + for (const block of depBlock.blocks) { + queue.push([block, usedExports]); + } + }; - const processDependency = dep => { - const reference = dep.getReference && dep.getReference(); - if(!reference) return; - const module = reference.module; - const importedNames = reference.importedNames; - const oldUsed = module.used; - const oldUsedExports = module.usedExports; - if(!oldUsed || (importedNames && (!oldUsedExports || !isSubset(oldUsedExports, importedNames)))) { - processModule(module, importedNames); + const processDependency = dep => { + const reference = dep.getReference && dep.getReference(); + if (!reference) return; + const module = reference.module; + const importedNames = reference.importedNames; + const oldUsed = module.used; + const oldUsedExports = module.usedExports; + if ( + !oldUsed || + (importedNames && + (!oldUsedExports || !isSubset(oldUsedExports, importedNames))) + ) { + processModule(module, importedNames); + } + }; + + for (const module of modules) { + module.used = false; } - }; - for(const module of modules) { - module.used = false; - } + const queue = []; + for (const chunk of compilation.chunks) { + if (chunk.entryModule) { + processModule(chunk.entryModule, true); + } + } - const queue = []; - for(const chunk of compilation.chunks) { - if(chunk.entryModule) { - processModule(chunk.entryModule, true); + while (queue.length) { + const queueItem = queue.pop(); + processDependenciesBlock(queueItem[0], queueItem[1]); } } - - while(queue.length) { - const queueItem = queue.pop(); - processDependenciesBlock(queueItem[0], queueItem[1]); - } - }); + ); }); } } diff --git a/lib/FlagInitialModulesAsUsedPlugin.js b/lib/FlagInitialModulesAsUsedPlugin.js index a38ea30a7..7272ddb3a 100644 --- a/lib/FlagInitialModulesAsUsedPlugin.js +++ b/lib/FlagInitialModulesAsUsedPlugin.js @@ -10,20 +10,26 @@ class FlagInitialModulesAsUsedPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("FlagInitialModulesAsUsedPlugin", (compilation) => { - compilation.hooks.afterOptimizeChunks.tap("FlagInitialModulesAsUsedPlugin", (chunks) => { - for(const chunk of chunks) { - if(!chunk.isOnlyInitial()) { - return; + compiler.hooks.compilation.tap( + "FlagInitialModulesAsUsedPlugin", + compilation => { + compilation.hooks.afterOptimizeChunks.tap( + "FlagInitialModulesAsUsedPlugin", + chunks => { + for (const chunk of chunks) { + if (!chunk.isOnlyInitial()) { + return; + } + for (const module of chunk.modulesIterable) { + module.used = true; + module.usedExports = true; + module.addReason(null, null, this.explanation); + } + } } - for(const module of chunk.modulesIterable) { - module.used = true; - module.usedExports = true; - module.addReason(null, null, this.explanation); - } - } - }); - }); + ); + } + ); } } diff --git a/lib/FunctionModulePlugin.js b/lib/FunctionModulePlugin.js index 5415b573d..7ae154583 100644 --- a/lib/FunctionModulePlugin.js +++ b/lib/FunctionModulePlugin.js @@ -12,8 +12,10 @@ class FunctionModulePlugin { } apply(compiler) { - compiler.hooks.compilation.tap("FunctionModulePlugin", (compilation) => { - new FunctionModuleTemplatePlugin().apply(compilation.moduleTemplates.javascript); + compiler.hooks.compilation.tap("FunctionModulePlugin", compilation => { + new FunctionModuleTemplatePlugin().apply( + compilation.moduleTemplates.javascript + ); }); } } diff --git a/lib/FunctionModuleTemplatePlugin.js b/lib/FunctionModuleTemplatePlugin.js index be5b5a252..0dd8ff637 100644 --- a/lib/FunctionModuleTemplatePlugin.js +++ b/lib/FunctionModuleTemplatePlugin.js @@ -9,62 +9,85 @@ const Template = require("./Template"); class FunctionModuleTemplatePlugin { apply(moduleTemplate) { - moduleTemplate.hooks.render.tap("FunctionModuleTemplatePlugin", (moduleSource, module) => { - const source = new ConcatSource(); - const args = [module.moduleArgument]; - // TODO remove HACK checking type for javascript - if(module.type && module.type.startsWith("javascript")) { - args.push(module.exportsArgument); - if(module.hasDependencies(d => d.requireWebpackRequire !== false)) { - args.push("__webpack_require__"); - } - } else if(module.type && module.type.startsWith("json")) { - // no additional arguments needed - } else { - args.push(module.exportsArgument, "__webpack_require__"); - } - source.add("/***/ (function(" + args.join(", ") + ") {\n\n"); - if(module.buildInfo.strict) source.add("\"use strict\";\n"); - source.add(moduleSource); - source.add("\n\n/***/ })"); - return source; - }); - - moduleTemplate.hooks.package.tap("FunctionModuleTemplatePlugin", (moduleSource, module) => { - if(moduleTemplate.runtimeTemplate.outputOptions.pathinfo) { + moduleTemplate.hooks.render.tap( + "FunctionModuleTemplatePlugin", + (moduleSource, module) => { const source = new ConcatSource(); - const req = module.readableIdentifier(moduleTemplate.runtimeTemplate.requestShortener); - source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n"); - source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n"); - source.add(" \\****" + req.replace(/./g, "*") + "****/\n"); - if(Array.isArray(module.buildMeta.providedExports) && module.buildMeta.providedExports.length === 0) - source.add(Template.toComment("no exports provided") + "\n"); - else if(Array.isArray(module.buildMeta.providedExports)) - source.add(Template.toComment("exports provided: " + module.buildMeta.providedExports.join(", ")) + "\n"); - else if(module.buildMeta.providedExports) - source.add(Template.toComment("no static exports found") + "\n"); - if(Array.isArray(module.usedExports) && module.usedExports.length === 0) - source.add(Template.toComment("no exports used") + "\n"); - else if(Array.isArray(module.usedExports)) - source.add(Template.toComment("exports used: " + module.usedExports.join(", ")) + "\n"); - else if(module.usedExports) - source.add(Template.toComment("all exports used") + "\n"); - if(module.optimizationBailout) { - for(const text of module.optimizationBailout) { - let code; - if(typeof text === "function") { - code = text(moduleTemplate.runtimeTemplate.requestShortener); - } else { - code = text; - } - source.add(Template.toComment(`${code}`) + "\n"); + const args = [module.moduleArgument]; + // TODO remove HACK checking type for javascript + if (module.type && module.type.startsWith("javascript")) { + args.push(module.exportsArgument); + if (module.hasDependencies(d => d.requireWebpackRequire !== false)) { + args.push("__webpack_require__"); } + } else if (module.type && module.type.startsWith("json")) { + // no additional arguments needed + } else { + args.push(module.exportsArgument, "__webpack_require__"); } + source.add("/***/ (function(" + args.join(", ") + ") {\n\n"); + if (module.buildInfo.strict) source.add('"use strict";\n'); source.add(moduleSource); + source.add("\n\n/***/ })"); return source; } - return moduleSource; - }); + ); + + moduleTemplate.hooks.package.tap( + "FunctionModuleTemplatePlugin", + (moduleSource, module) => { + if (moduleTemplate.runtimeTemplate.outputOptions.pathinfo) { + const source = new ConcatSource(); + const req = module.readableIdentifier( + moduleTemplate.runtimeTemplate.requestShortener + ); + source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n"); + source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n"); + source.add(" \\****" + req.replace(/./g, "*") + "****/\n"); + if ( + Array.isArray(module.buildMeta.providedExports) && + module.buildMeta.providedExports.length === 0 + ) + source.add(Template.toComment("no exports provided") + "\n"); + else if (Array.isArray(module.buildMeta.providedExports)) + source.add( + Template.toComment( + "exports provided: " + + module.buildMeta.providedExports.join(", ") + ) + "\n" + ); + else if (module.buildMeta.providedExports) + source.add(Template.toComment("no static exports found") + "\n"); + if ( + Array.isArray(module.usedExports) && + module.usedExports.length === 0 + ) + source.add(Template.toComment("no exports used") + "\n"); + else if (Array.isArray(module.usedExports)) + source.add( + Template.toComment( + "exports used: " + module.usedExports.join(", ") + ) + "\n" + ); + else if (module.usedExports) + source.add(Template.toComment("all exports used") + "\n"); + if (module.optimizationBailout) { + for (const text of module.optimizationBailout) { + let code; + if (typeof text === "function") { + code = text(moduleTemplate.runtimeTemplate.requestShortener); + } else { + code = text; + } + source.add(Template.toComment(`${code}`) + "\n"); + } + } + source.add(moduleSource); + return source; + } + return moduleSource; + } + ); moduleTemplate.hooks.hash.tap("FunctionModuleTemplatePlugin", hash => { hash.update("FunctionModuleTemplatePlugin"); diff --git a/lib/GraphHelpers.js b/lib/GraphHelpers.js index 1f2cf8362..cb61b177c 100644 --- a/lib/GraphHelpers.js +++ b/lib/GraphHelpers.js @@ -1,17 +1,17 @@ exports.connectChunkGroupAndChunk = (chunkGroup, chunk) => { - if(chunkGroup.pushChunk(chunk)) { + if (chunkGroup.pushChunk(chunk)) { chunk.addGroup(chunkGroup); } }; exports.connectChunkGroupParentAndChild = (parent, child) => { - if(parent.addChild(child)) { + if (parent.addChild(child)) { child.addParent(parent); } }; exports.connectChunkAndModule = (chunk, module) => { - if(module.addChunk(chunk)) { + if (module.addChunk(chunk)) { chunk.addModule(module); } }; @@ -22,7 +22,7 @@ exports.disconnectChunkAndModule = (chunk, module) => { }; exports.connectDependenciesBlockAndChunkGroup = (depBlock, chunkGroup) => { - if(chunkGroup.addBlock(depBlock)) { + if (chunkGroup.addBlock(depBlock)) { depBlock.chunkGroup = chunkGroup; } }; diff --git a/lib/HashedModuleIdsPlugin.js b/lib/HashedModuleIdsPlugin.js index 54320e61f..aeb9f1d93 100644 --- a/lib/HashedModuleIdsPlugin.js +++ b/lib/HashedModuleIdsPlugin.js @@ -12,35 +12,40 @@ class HashedModuleIdsPlugin { constructor(options) { validateOptions(schema, options || {}, "Hashed Module Ids Plugin"); - this.options = Object.assign({ - context: null, - hashFunction: "md4", - hashDigest: "base64", - hashDigestLength: 4 - }, options); + this.options = Object.assign( + { + context: null, + hashFunction: "md4", + hashDigest: "base64", + hashDigestLength: 4 + }, + options + ); } apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("HashedModuleIdsPlugin", (compilation) => { + compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => { const usedIds = new Set(); - compilation.hooks.beforeModuleIds.tap("HashedModuleIdsPlugin", (modules) => { - for(const module of modules) { - if(module.id === null && module.libIdent) { - const id = module.libIdent({ - context: this.options.context || compiler.options.context - }); - const hash = createHash(options.hashFunction); - hash.update(id); - const hashId = hash.digest(options.hashDigest); - let len = options.hashDigestLength; - while(usedIds.has(hashId.substr(0, len))) - len++; - module.id = hashId.substr(0, len); - usedIds.add(module.id); + compilation.hooks.beforeModuleIds.tap( + "HashedModuleIdsPlugin", + modules => { + for (const module of modules) { + if (module.id === null && module.libIdent) { + const id = module.libIdent({ + context: this.options.context || compiler.options.context + }); + const hash = createHash(options.hashFunction); + hash.update(id); + const hashId = hash.digest(options.hashDigest); + let len = options.hashDigestLength; + while (usedIds.has(hashId.substr(0, len))) len++; + module.id = hashId.substr(0, len); + usedIds.add(module.id); + } } } - }); + ); }); } } diff --git a/lib/HotModuleReplacement.runtime.js b/lib/HotModuleReplacement.runtime.js index 5412d9a82..176f84d07 100644 --- a/lib/HotModuleReplacement.runtime.js +++ b/lib/HotModuleReplacement.runtime.js @@ -4,7 +4,6 @@ */ /*global $hash$ $requestTimeout$ installedModules $require$ hotDownloadManifest hotDownloadUpdateChunk hotDisposeChunk modules */ module.exports = function() { - var hotApplyOnUpdate = true; var hotCurrentHash = $hash$; // eslint-disable-line no-unused-vars var hotRequestTimeout = $requestTimeout$; @@ -13,22 +12,27 @@ module.exports = function() { var hotCurrentParents = []; // eslint-disable-line no-unused-vars var hotCurrentParentsTemp = []; // eslint-disable-line no-unused-vars - function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars + function hotCreateRequire(moduleId) { + // eslint-disable-line no-unused-vars var me = installedModules[moduleId]; - if(!me) return $require$; + if (!me) return $require$; var fn = function(request) { - if(me.hot.active) { - if(installedModules[request]) { - if(!installedModules[request].parents.includes(moduleId)) + if (me.hot.active) { + if (installedModules[request]) { + if (!installedModules[request].parents.includes(moduleId)) installedModules[request].parents.push(moduleId); } else { hotCurrentParents = [moduleId]; hotCurrentChildModule = request; } - if(!me.children.includes(request)) - me.children.push(request); + if (!me.children.includes(request)) me.children.push(request); } else { - console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId); + console.warn( + "[HMR] unexpected require(" + + request + + ") from disposed module " + + moduleId + ); hotCurrentParents = []; } return $require$(request); @@ -45,14 +49,16 @@ module.exports = function() { } }; }; - for(var name in $require$) { - if(Object.prototype.hasOwnProperty.call($require$, name) && name !== "e") { + for (var name in $require$) { + if ( + Object.prototype.hasOwnProperty.call($require$, name) && + name !== "e" + ) { Object.defineProperty(fn, name, ObjectFactory(name)); } } fn.e = function(chunkId) { - if(hotStatus === "ready") - hotSetStatus("prepare"); + if (hotStatus === "ready") hotSetStatus("prepare"); hotChunksLoading++; return $require$.e(chunkId).then(finishChunkLoading, function(err) { finishChunkLoading(); @@ -61,11 +67,11 @@ module.exports = function() { function finishChunkLoading() { hotChunksLoading--; - if(hotStatus === "prepare") { - if(!hotWaitingFilesMap[chunkId]) { + if (hotStatus === "prepare") { + if (!hotWaitingFilesMap[chunkId]) { hotEnsureUpdateChunk(chunkId); } - if(hotChunksLoading === 0 && hotWaitingFiles === 0) { + if (hotChunksLoading === 0 && hotWaitingFiles === 0) { hotUpdateDownloaded(); } } @@ -74,7 +80,8 @@ module.exports = function() { return fn; } - function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars + function hotCreateModule(moduleId) { + // eslint-disable-line no-unused-vars var hot = { // private stuff _acceptedDependencies: {}, @@ -87,24 +94,19 @@ module.exports = function() { // Module API active: true, accept: function(dep, callback) { - if(typeof dep === "undefined") - hot._selfAccepted = true; - else if(typeof dep === "function") - hot._selfAccepted = dep; - else if(typeof dep === "object") - for(var i = 0; i < dep.length; i++) + if (typeof dep === "undefined") hot._selfAccepted = true; + else if (typeof dep === "function") hot._selfAccepted = dep; + else if (typeof dep === "object") + for (var i = 0; i < dep.length; i++) hot._acceptedDependencies[dep[i]] = callback || function() {}; - else - hot._acceptedDependencies[dep] = callback || function() {}; + else hot._acceptedDependencies[dep] = callback || function() {}; }, decline: function(dep) { - if(typeof dep === "undefined") - hot._selfDeclined = true; - else if(typeof dep === "object") - for(var i = 0; i < dep.length; i++) + if (typeof dep === "undefined") hot._selfDeclined = true; + else if (typeof dep === "object") + for (var i = 0; i < dep.length; i++) hot._declinedDependencies[dep[i]] = true; - else - hot._declinedDependencies[dep] = true; + else hot._declinedDependencies[dep] = true; }, dispose: function(callback) { hot._disposeHandlers.push(callback); @@ -114,14 +116,14 @@ module.exports = function() { }, removeDisposeHandler: function(callback) { var idx = hot._disposeHandlers.indexOf(callback); - if(idx >= 0) hot._disposeHandlers.splice(idx, 1); + if (idx >= 0) hot._disposeHandlers.splice(idx, 1); }, // Management API check: hotCheck, apply: hotApply, status: function(l) { - if(!l) return hotStatus; + if (!l) return hotStatus; hotStatusHandlers.push(l); }, addStatusHandler: function(l) { @@ -129,7 +131,7 @@ module.exports = function() { }, removeStatusHandler: function(l) { var idx = hotStatusHandlers.indexOf(l); - if(idx >= 0) hotStatusHandlers.splice(idx, 1); + if (idx >= 0) hotStatusHandlers.splice(idx, 1); }, //inherit from previous dispose call @@ -144,7 +146,7 @@ module.exports = function() { function hotSetStatus(newStatus) { hotStatus = newStatus; - for(var i = 0; i < hotStatusHandlers.length; i++) + for (var i = 0; i < hotStatusHandlers.length; i++) hotStatusHandlers[i].call(null, newStatus); } @@ -160,16 +162,17 @@ module.exports = function() { var hotUpdate, hotUpdateNewHash; function toModuleId(id) { - var isNumber = (+id) + "" === id; + var isNumber = +id + "" === id; return isNumber ? +id : id; } function hotCheck(apply) { - if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status"); + if (hotStatus !== "idle") + throw new Error("check() is only allowed in idle status"); hotApplyOnUpdate = apply; hotSetStatus("check"); return hotDownloadManifest(hotRequestTimeout).then(function(update) { - if(!update) { + if (!update) { hotSetStatus("idle"); return null; } @@ -187,33 +190,39 @@ module.exports = function() { }); hotUpdate = {}; /*foreachInstalledChunks*/ - { // eslint-disable-line no-lone-blocks + { + // eslint-disable-line no-lone-blocks /*globals chunkId */ hotEnsureUpdateChunk(chunkId); } - if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) { + if ( + hotStatus === "prepare" && + hotChunksLoading === 0 && + hotWaitingFiles === 0 + ) { hotUpdateDownloaded(); } return promise; }); } - function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars - if(!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId]) + function hotAddUpdateChunk(chunkId, moreModules) { + // eslint-disable-line no-unused-vars + if (!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId]) return; hotRequestedFilesMap[chunkId] = false; - for(var moduleId in moreModules) { - if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { + for (var moduleId in moreModules) { + if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { hotUpdate[moduleId] = moreModules[moduleId]; } } - if(--hotWaitingFiles === 0 && hotChunksLoading === 0) { + if (--hotWaitingFiles === 0 && hotChunksLoading === 0) { hotUpdateDownloaded(); } } function hotEnsureUpdateChunk(chunkId) { - if(!hotAvailableFilesMap[chunkId]) { + if (!hotAvailableFilesMap[chunkId]) { hotWaitingFilesMap[chunkId] = true; } else { hotRequestedFilesMap[chunkId] = true; @@ -226,25 +235,27 @@ module.exports = function() { hotSetStatus("ready"); var deferred = hotDeferred; hotDeferred = null; - if(!deferred) return; - if(hotApplyOnUpdate) { + if (!deferred) return; + if (hotApplyOnUpdate) { // Wrap deferred object in Promise to mark it as a well-handled Promise to // avoid triggering uncaught exception warning in Chrome. // See https://bugs.chromium.org/p/chromium/issues/detail?id=465666 - Promise.resolve().then(function() { - return hotApply(hotApplyOnUpdate); - }).then( - function(result) { - deferred.resolve(result); - }, - function(err) { - deferred.reject(err); - } - ); + Promise.resolve() + .then(function() { + return hotApply(hotApplyOnUpdate); + }) + .then( + function(result) { + deferred.resolve(result); + }, + function(err) { + deferred.reject(err); + } + ); } else { var outdatedModules = []; - for(var id in hotUpdate) { - if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { + for (var id in hotUpdate) { + if (Object.prototype.hasOwnProperty.call(hotUpdate, id)) { outdatedModules.push(toModuleId(id)); } } @@ -253,7 +264,8 @@ module.exports = function() { } function hotApply(options) { - if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status"); + if (hotStatus !== "ready") + throw new Error("apply() is only allowed in ready status"); options = options || {}; var cb; @@ -272,32 +284,31 @@ module.exports = function() { id: id }; }); - while(queue.length > 0) { + while (queue.length > 0) { var queueItem = queue.pop(); var moduleId = queueItem.id; var chain = queueItem.chain; module = installedModules[moduleId]; - if(!module || module.hot._selfAccepted) - continue; - if(module.hot._selfDeclined) { + if (!module || module.hot._selfAccepted) continue; + if (module.hot._selfDeclined) { return { type: "self-declined", chain: chain, moduleId: moduleId }; } - if(module.hot._main) { + if (module.hot._main) { return { type: "unaccepted", chain: chain, moduleId: moduleId }; } - for(var i = 0; i < module.parents.length; i++) { + for (var i = 0; i < module.parents.length; i++) { var parentId = module.parents[i]; var parent = installedModules[parentId]; - if(!parent) continue; - if(parent.hot._declinedDependencies[moduleId]) { + if (!parent) continue; + if (parent.hot._declinedDependencies[moduleId]) { return { type: "declined", chain: chain.concat([parentId]), @@ -305,9 +316,9 @@ module.exports = function() { parentId: parentId }; } - if(outdatedModules.includes(parentId)) continue; - if(parent.hot._acceptedDependencies[moduleId]) { - if(!outdatedDependencies[parentId]) + if (outdatedModules.includes(parentId)) continue; + if (parent.hot._acceptedDependencies[moduleId]) { + if (!outdatedDependencies[parentId]) outdatedDependencies[parentId] = []; addAllToSet(outdatedDependencies[parentId], [moduleId]); continue; @@ -330,10 +341,9 @@ module.exports = function() { } function addAllToSet(a, b) { - for(var i = 0; i < b.length; i++) { + for (var i = 0; i < b.length; i++) { var item = b[i]; - if(!a.includes(item)) - a.push(item); + if (!a.includes(item)) a.push(item); } } @@ -344,14 +354,16 @@ module.exports = function() { var appliedUpdate = {}; var warnUnexpectedRequire = function warnUnexpectedRequire() { - console.warn("[HMR] unexpected require(" + result.moduleId + ") to disposed module"); + console.warn( + "[HMR] unexpected require(" + result.moduleId + ") to disposed module" + ); }; - for(var id in hotUpdate) { - if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { + for (var id in hotUpdate) { + if (Object.prototype.hasOwnProperty.call(hotUpdate, id)) { moduleId = toModuleId(id); var result; - if(hotUpdate[id]) { + if (hotUpdate[id]) { result = getAffectedStuff(moduleId); } else { result = { @@ -363,57 +375,72 @@ module.exports = function() { var doApply = false; var doDispose = false; var chainInfo = ""; - if(result.chain) { + if (result.chain) { chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); } - switch(result.type) { + switch (result.type) { case "self-declined": - if(options.onDeclined) - options.onDeclined(result); - if(!options.ignoreDeclined) - abortError = new Error("Aborted because of self decline: " + result.moduleId + chainInfo); + if (options.onDeclined) options.onDeclined(result); + if (!options.ignoreDeclined) + abortError = new Error( + "Aborted because of self decline: " + + result.moduleId + + chainInfo + ); break; case "declined": - if(options.onDeclined) - options.onDeclined(result); - if(!options.ignoreDeclined) - abortError = new Error("Aborted because of declined dependency: " + result.moduleId + " in " + result.parentId + chainInfo); + if (options.onDeclined) options.onDeclined(result); + if (!options.ignoreDeclined) + abortError = new Error( + "Aborted because of declined dependency: " + + result.moduleId + + " in " + + result.parentId + + chainInfo + ); break; case "unaccepted": - if(options.onUnaccepted) - options.onUnaccepted(result); - if(!options.ignoreUnaccepted) - abortError = new Error("Aborted because " + moduleId + " is not accepted" + chainInfo); + if (options.onUnaccepted) options.onUnaccepted(result); + if (!options.ignoreUnaccepted) + abortError = new Error( + "Aborted because " + moduleId + " is not accepted" + chainInfo + ); break; case "accepted": - if(options.onAccepted) - options.onAccepted(result); + if (options.onAccepted) options.onAccepted(result); doApply = true; break; case "disposed": - if(options.onDisposed) - options.onDisposed(result); + if (options.onDisposed) options.onDisposed(result); doDispose = true; break; default: throw new Error("Unexception type " + result.type); } - if(abortError) { + if (abortError) { hotSetStatus("abort"); return Promise.reject(abortError); } - if(doApply) { + if (doApply) { appliedUpdate[moduleId] = hotUpdate[moduleId]; addAllToSet(outdatedModules, result.outdatedModules); - for(moduleId in result.outdatedDependencies) { - if(Object.prototype.hasOwnProperty.call(result.outdatedDependencies, moduleId)) { - if(!outdatedDependencies[moduleId]) + for (moduleId in result.outdatedDependencies) { + if ( + Object.prototype.hasOwnProperty.call( + result.outdatedDependencies, + moduleId + ) + ) { + if (!outdatedDependencies[moduleId]) outdatedDependencies[moduleId] = []; - addAllToSet(outdatedDependencies[moduleId], result.outdatedDependencies[moduleId]); + addAllToSet( + outdatedDependencies[moduleId], + result.outdatedDependencies[moduleId] + ); } } } - if(doDispose) { + if (doDispose) { addAllToSet(outdatedModules, [result.moduleId]); appliedUpdate[moduleId] = warnUnexpectedRequire; } @@ -422,9 +449,12 @@ module.exports = function() { // Store self accepted outdated modules to require them later by the module system var outdatedSelfAcceptedModules = []; - for(i = 0; i < outdatedModules.length; i++) { + for (i = 0; i < outdatedModules.length; i++) { moduleId = outdatedModules[i]; - if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted) + if ( + installedModules[moduleId] && + installedModules[moduleId].hot._selfAccepted + ) outdatedSelfAcceptedModules.push({ module: moduleId, errorHandler: installedModules[moduleId].hot._selfAccepted @@ -434,23 +464,23 @@ module.exports = function() { // Now in "dispose" phase hotSetStatus("dispose"); Object.keys(hotAvailableFilesMap).forEach(function(chunkId) { - if(hotAvailableFilesMap[chunkId] === false) { + if (hotAvailableFilesMap[chunkId] === false) { hotDisposeChunk(chunkId); } }); var idx; var queue = outdatedModules.slice(); - while(queue.length > 0) { + while (queue.length > 0) { moduleId = queue.pop(); module = installedModules[moduleId]; - if(!module) continue; + if (!module) continue; var data = {}; // Call dispose handlers var disposeHandlers = module.hot._disposeHandlers; - for(j = 0; j < disposeHandlers.length; j++) { + for (j = 0; j < disposeHandlers.length; j++) { cb = disposeHandlers[j]; cb(data); } @@ -466,11 +496,11 @@ module.exports = function() { delete outdatedDependencies[moduleId]; // remove "parents" references from all children - for(j = 0; j < module.children.length; j++) { + for (j = 0; j < module.children.length; j++) { var child = installedModules[module.children[j]]; - if(!child) continue; + if (!child) continue; idx = child.parents.indexOf(moduleId); - if(idx >= 0) { + if (idx >= 0) { child.parents.splice(idx, 1); } } @@ -479,15 +509,17 @@ module.exports = function() { // remove outdated dependency from module children var dependency; var moduleOutdatedDependencies; - for(moduleId in outdatedDependencies) { - if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) { + for (moduleId in outdatedDependencies) { + if ( + Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId) + ) { module = installedModules[moduleId]; - if(module) { + if (module) { moduleOutdatedDependencies = outdatedDependencies[moduleId]; - for(j = 0; j < moduleOutdatedDependencies.length; j++) { + for (j = 0; j < moduleOutdatedDependencies.length; j++) { dependency = moduleOutdatedDependencies[j]; idx = module.children.indexOf(dependency); - if(idx >= 0) module.children.splice(idx, 1); + if (idx >= 0) module.children.splice(idx, 1); } } } @@ -499,34 +531,36 @@ module.exports = function() { hotCurrentHash = hotUpdateNewHash; // insert new code - for(moduleId in appliedUpdate) { - if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) { + for (moduleId in appliedUpdate) { + if (Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) { modules[moduleId] = appliedUpdate[moduleId]; } } // call accept handlers var error = null; - for(moduleId in outdatedDependencies) { - if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) { + for (moduleId in outdatedDependencies) { + if ( + Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId) + ) { module = installedModules[moduleId]; - if(module) { + if (module) { moduleOutdatedDependencies = outdatedDependencies[moduleId]; var callbacks = []; - for(i = 0; i < moduleOutdatedDependencies.length; i++) { + for (i = 0; i < moduleOutdatedDependencies.length; i++) { dependency = moduleOutdatedDependencies[i]; cb = module.hot._acceptedDependencies[dependency]; - if(cb) { - if(callbacks.includes(cb)) continue; + if (cb) { + if (callbacks.includes(cb)) continue; callbacks.push(cb); } } - for(i = 0; i < callbacks.length; i++) { + for (i = 0; i < callbacks.length; i++) { cb = callbacks[i]; try { cb(moduleOutdatedDependencies); - } catch(err) { - if(options.onErrored) { + } catch (err) { + if (options.onErrored) { options.onErrored({ type: "accept-errored", moduleId: moduleId, @@ -534,9 +568,8 @@ module.exports = function() { error: err }); } - if(!options.ignoreErrored) { - if(!error) - error = err; + if (!options.ignoreErrored) { + if (!error) error = err; } } } @@ -545,18 +578,18 @@ module.exports = function() { } // Load self accepted modules - for(i = 0; i < outdatedSelfAcceptedModules.length; i++) { + for (i = 0; i < outdatedSelfAcceptedModules.length; i++) { var item = outdatedSelfAcceptedModules[i]; moduleId = item.module; hotCurrentParents = [moduleId]; try { $require$(moduleId); - } catch(err) { - if(typeof item.errorHandler === "function") { + } catch (err) { + if (typeof item.errorHandler === "function") { try { item.errorHandler(err); - } catch(err2) { - if(options.onErrored) { + } catch (err2) { + if (options.onErrored) { options.onErrored({ type: "self-accept-error-handler-errored", moduleId: moduleId, @@ -564,31 +597,28 @@ module.exports = function() { originalError: err }); } - if(!options.ignoreErrored) { - if(!error) - error = err2; + if (!options.ignoreErrored) { + if (!error) error = err2; } - if(!error) - error = err; + if (!error) error = err; } } else { - if(options.onErrored) { + if (options.onErrored) { options.onErrored({ type: "self-accept-errored", moduleId: moduleId, error: err }); } - if(!options.ignoreErrored) { - if(!error) - error = err; + if (!options.ignoreErrored) { + if (!error) error = err; } } } } // handle errors in accept handlers and self accepted module load - if(error) { + if (error) { hotSetStatus("fail"); return Promise.reject(error); } diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index 9a33e223f..aec1c0a52 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -25,255 +25,382 @@ module.exports = class HotModuleReplacementPlugin { const multiStep = this.multiStep; const fullBuildTimeout = this.fullBuildTimeout; const requestTimeout = this.requestTimeout; - const hotUpdateChunkFilename = compiler.options.output.hotUpdateChunkFilename; + const hotUpdateChunkFilename = + compiler.options.output.hotUpdateChunkFilename; const hotUpdateMainFilename = compiler.options.output.hotUpdateMainFilename; - compiler.hooks.additionalPass.tapAsync("HotModuleReplacementPlugin", (callback) => { - if(multiStep) - return setTimeout(callback, fullBuildTimeout); - return callback(); - }); - compiler.hooks.compilation.tap("HotModuleReplacementPlugin", (compilation, { - normalModuleFactory - }) => { - const hotUpdateChunkTemplate = compilation.hotUpdateChunkTemplate; - if(!hotUpdateChunkTemplate) return; + compiler.hooks.additionalPass.tapAsync( + "HotModuleReplacementPlugin", + callback => { + if (multiStep) return setTimeout(callback, fullBuildTimeout); + return callback(); + } + ); + compiler.hooks.compilation.tap( + "HotModuleReplacementPlugin", + (compilation, { normalModuleFactory }) => { + const hotUpdateChunkTemplate = compilation.hotUpdateChunkTemplate; + if (!hotUpdateChunkTemplate) return; - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - compilation.dependencyFactories.set(ModuleHotAcceptDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ModuleHotAcceptDependency, new ModuleHotAcceptDependency.Template()); + compilation.dependencyFactories.set( + ModuleHotAcceptDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ModuleHotAcceptDependency, + new ModuleHotAcceptDependency.Template() + ); - compilation.dependencyFactories.set(ModuleHotDeclineDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ModuleHotDeclineDependency, new ModuleHotDeclineDependency.Template()); + compilation.dependencyFactories.set( + ModuleHotDeclineDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ModuleHotDeclineDependency, + new ModuleHotDeclineDependency.Template() + ); - compilation.hooks.record.tap("HotModuleReplacementPlugin", (compilation, records) => { - if(records.hash === compilation.hash) return; - records.hash = compilation.hash; - records.moduleHashs = {}; - for(const module of compilation.modules) { - const identifier = module.identifier(); - const hash = createHash(compilation.outputOptions.hashFunction); - module.updateHash(hash); - records.moduleHashs[identifier] = hash.digest("hex"); - } - records.chunkHashs = {}; - for(const chunk of compilation.chunks) { - records.chunkHashs[chunk.id] = chunk.hash; - } - records.chunkModuleIds = {}; - for(const chunk of compilation.chunks) { - records.chunkModuleIds[chunk.id] = Array.from(chunk.modulesIterable, m => m.id); - } - }); - let initialPass = false; - let recompilation = false; - compilation.hooks.afterHash.tap("HotModuleReplacementPlugin", () => { - let records = compilation.records; - if(!records) { - initialPass = true; - return; - } - if(!records.hash) - initialPass = true; - const preHash = records.preHash || "x"; - const prepreHash = records.prepreHash || "x"; - if(preHash === compilation.hash) { - recompilation = true; - compilation.modifyHash(prepreHash); - return; - } - records.prepreHash = records.hash || "x"; - records.preHash = compilation.hash; - compilation.modifyHash(records.prepreHash); - }); - compilation.hooks.shouldGenerateChunkAssets.tap("HotModuleReplacementPlugin", () => { - if(multiStep && !recompilation && !initialPass) - return false; - }); - compilation.hooks.needAdditionalPass.tap("HotModuleReplacementPlugin", () => { - if(multiStep && !recompilation && !initialPass) - return true; - }); - compilation.hooks.additionalChunkAssets.tap("HotModuleReplacementPlugin", () => { - const records = compilation.records; - if(records.hash === compilation.hash) return; - if(!records.moduleHashs || !records.chunkHashs || !records.chunkModuleIds) return; - for(const module of compilation.modules) { - const identifier = module.identifier(); - let hash = createHash(compilation.outputOptions.hashFunction); - module.updateHash(hash); - hash = hash.digest("hex"); - module.hotUpdate = records.moduleHashs[identifier] !== hash; - } - const hotUpdateMainContent = { - h: compilation.hash, - c: {}, - }; - for(let chunkId of Object.keys(records.chunkHashs)) { - chunkId = isNaN(+chunkId) ? chunkId : +chunkId; - const currentChunk = compilation.chunks.find(chunk => chunk.id === chunkId); - if(currentChunk) { - const newModules = currentChunk.getModules().filter(module => module.hotUpdate); - const allModules = new Set(); - for(const module of currentChunk.modulesIterable) { - allModules.add(module.id); + compilation.hooks.record.tap( + "HotModuleReplacementPlugin", + (compilation, records) => { + if (records.hash === compilation.hash) return; + records.hash = compilation.hash; + records.moduleHashs = {}; + for (const module of compilation.modules) { + const identifier = module.identifier(); + const hash = createHash(compilation.outputOptions.hashFunction); + module.updateHash(hash); + records.moduleHashs[identifier] = hash.digest("hex"); } - const removedModules = records.chunkModuleIds[chunkId].filter(id => !allModules.has(id)); - if(newModules.length > 0 || removedModules.length > 0) { - const source = hotUpdateChunkTemplate.render(chunkId, newModules, removedModules, compilation.hash, compilation.moduleTemplates.javascript, compilation.dependencyTemplates); - const filename = compilation.getPath(hotUpdateChunkFilename, { - hash: records.hash, - chunk: currentChunk - }); - compilation.additionalChunkAssets.push(filename); - compilation.assets[filename] = source; - hotUpdateMainContent.c[chunkId] = true; - currentChunk.files.push(filename); - compilation.hooks.chunkAsset.call("HotModuleReplacementPlugin", currentChunk, filename); + records.chunkHashs = {}; + for (const chunk of compilation.chunks) { + records.chunkHashs[chunk.id] = chunk.hash; } - } else { - hotUpdateMainContent.c[chunkId] = false; - } - } - const source = new RawSource(JSON.stringify(hotUpdateMainContent)); - const filename = compilation.getPath(hotUpdateMainFilename, { - hash: records.hash - }); - compilation.assets[filename] = source; - }); - - const mainTemplate = compilation.mainTemplate; - - mainTemplate.hooks.hash.tap("HotModuleReplacementPlugin", hash => { - hash.update("HotMainTemplateDecorator"); - }); - - mainTemplate.hooks.moduleRequire.tap("HotModuleReplacementPlugin", (_, chunk, hash, varModuleId) => { - return `hotCreateRequire(${varModuleId})`; - }); - - mainTemplate.hooks.requireExtensions.tap("HotModuleReplacementPlugin", source => { - const buf = [source]; - buf.push(""); - buf.push("// __webpack_hash__"); - buf.push(mainTemplate.requireFn + ".h = function() { return hotCurrentHash; };"); - return Template.asString(buf); - }); - - const needChunkLoadingCode = chunk => { - for(const chunkGroup of chunk.groupsIterable) { - if(chunkGroup.chunks.length > 1) return true; - if(chunkGroup.getNumberOfChildren() > 0) return true; - } - return false; - }; - - mainTemplate.hooks.bootstrap.tap("HotModuleReplacementPlugin", (source, chunk, hash) => { - source = mainTemplate.hooks.hotBootstrap.call(source, chunk, hash); - return Template.asString([ - source, - "", - hotInitCode - .replace(/\$require\$/g, mainTemplate.requireFn) - .replace(/\$hash\$/g, JSON.stringify(hash)) - .replace(/\$requestTimeout\$/g, requestTimeout) - .replace(/\/\*foreachInstalledChunks\*\//g, needChunkLoadingCode(chunk) ? "for(var chunkId in installedChunks)" : `var chunkId = ${JSON.stringify(chunk.id)};`) - ]); - }); - - mainTemplate.hooks.globalHash.tap("HotModuleReplacementPlugin", () => true); - - mainTemplate.hooks.currentHash.tap("HotModuleReplacementPlugin", (_, length) => { - if(isFinite(length)) - return `hotCurrentHash.substr(0, ${length})`; - else - return "hotCurrentHash"; - }); - - mainTemplate.hooks.moduleObj.tap("HotModuleReplacementPlugin", (source, chunk, hash, varModuleId) => { - return Template.asString([ - `${source},`, - `hot: hotCreateModule(${varModuleId}),`, - "parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),", - "children: []" - ]); - }); - - const handler = (parser, parserOptions) => { - parser.hooks.expression.for("__webpack_hash__").tap("HotModuleReplacementPlugin", ParserHelpers.toConstantDependencyWithWebpackRequire(parser, "__webpack_require__.h()")); - parser.hooks.evaluateTypeof.for("__webpack_hash__").tap("HotModuleReplacementPlugin", ParserHelpers.evaluateToString("string")); - parser.hooks.evaluateIdentifier.for("module.hot").tap({ - name: "HotModuleReplacementPlugin", - before: "NodeStuffPlugin" - }, expr => { - return ParserHelpers.evaluateToIdentifier("module.hot", !!parser.state.compilation.hotUpdateChunkTemplate)(expr); - }); - // TODO webpack 5: refactor this, no custom hooks - if(!parser.hooks.hotAcceptCallback) - parser.hooks.hotAcceptCallback = new SyncBailHook(["expression", "requests"]); - if(!parser.hooks.hotAcceptWithoutCallback) - parser.hooks.hotAcceptWithoutCallback = new SyncBailHook(["expression", "requests"]); - parser.hooks.call.for("module.hot.accept").tap("HotModuleReplacementPlugin", expr => { - if(!parser.state.compilation.hotUpdateChunkTemplate) return false; - if(expr.arguments.length >= 1) { - const arg = parser.evaluateExpression(expr.arguments[0]); - let params = []; - let requests = []; - if(arg.isString()) { - params = [arg]; - } else if(arg.isArray()) { - params = arg.items.filter(param => param.isString()); - } - if(params.length > 0) { - params.forEach((param, idx) => { - const request = param.string; - const dep = new ModuleHotAcceptDependency(request, param.range); - dep.optional = true; - dep.loc = Object.create(expr.loc); - dep.loc.index = idx; - parser.state.module.addDependency(dep); - requests.push(request); - }); - if(expr.arguments.length > 1) - parser.hooks.hotAcceptCallback.call(expr.arguments[1], requests); - else - parser.hooks.hotAcceptWithoutCallback.call(expr, requests); + records.chunkModuleIds = {}; + for (const chunk of compilation.chunks) { + records.chunkModuleIds[chunk.id] = Array.from( + chunk.modulesIterable, + m => m.id + ); } } + ); + let initialPass = false; + let recompilation = false; + compilation.hooks.afterHash.tap("HotModuleReplacementPlugin", () => { + let records = compilation.records; + if (!records) { + initialPass = true; + return; + } + if (!records.hash) initialPass = true; + const preHash = records.preHash || "x"; + const prepreHash = records.prepreHash || "x"; + if (preHash === compilation.hash) { + recompilation = true; + compilation.modifyHash(prepreHash); + return; + } + records.prepreHash = records.hash || "x"; + records.preHash = compilation.hash; + compilation.modifyHash(records.prepreHash); }); - parser.hooks.call.for("module.hot.decline").tap("HotModuleReplacementPlugin", expr => { - if(!parser.state.compilation.hotUpdateChunkTemplate) return false; - if(expr.arguments.length === 1) { - const arg = parser.evaluateExpression(expr.arguments[0]); - let params = []; - if(arg.isString()) { - params = [arg]; - } else if(arg.isArray()) { - params = arg.items.filter(param => param.isString()); + compilation.hooks.shouldGenerateChunkAssets.tap( + "HotModuleReplacementPlugin", + () => { + if (multiStep && !recompilation && !initialPass) return false; + } + ); + compilation.hooks.needAdditionalPass.tap( + "HotModuleReplacementPlugin", + () => { + if (multiStep && !recompilation && !initialPass) return true; + } + ); + compilation.hooks.additionalChunkAssets.tap( + "HotModuleReplacementPlugin", + () => { + const records = compilation.records; + if (records.hash === compilation.hash) return; + if ( + !records.moduleHashs || + !records.chunkHashs || + !records.chunkModuleIds + ) + return; + for (const module of compilation.modules) { + const identifier = module.identifier(); + let hash = createHash(compilation.outputOptions.hashFunction); + module.updateHash(hash); + hash = hash.digest("hex"); + module.hotUpdate = records.moduleHashs[identifier] !== hash; } - params.forEach((param, idx) => { - const dep = new ModuleHotDeclineDependency(param.string, param.range); - dep.optional = true; - dep.loc = Object.create(expr.loc); - dep.loc.index = idx; - parser.state.module.addDependency(dep); + const hotUpdateMainContent = { + h: compilation.hash, + c: {} + }; + for (let chunkId of Object.keys(records.chunkHashs)) { + chunkId = isNaN(+chunkId) ? chunkId : +chunkId; + const currentChunk = compilation.chunks.find( + chunk => chunk.id === chunkId + ); + if (currentChunk) { + const newModules = currentChunk + .getModules() + .filter(module => module.hotUpdate); + const allModules = new Set(); + for (const module of currentChunk.modulesIterable) { + allModules.add(module.id); + } + const removedModules = records.chunkModuleIds[chunkId].filter( + id => !allModules.has(id) + ); + if (newModules.length > 0 || removedModules.length > 0) { + const source = hotUpdateChunkTemplate.render( + chunkId, + newModules, + removedModules, + compilation.hash, + compilation.moduleTemplates.javascript, + compilation.dependencyTemplates + ); + const filename = compilation.getPath(hotUpdateChunkFilename, { + hash: records.hash, + chunk: currentChunk + }); + compilation.additionalChunkAssets.push(filename); + compilation.assets[filename] = source; + hotUpdateMainContent.c[chunkId] = true; + currentChunk.files.push(filename); + compilation.hooks.chunkAsset.call( + "HotModuleReplacementPlugin", + currentChunk, + filename + ); + } + } else { + hotUpdateMainContent.c[chunkId] = false; + } + } + const source = new RawSource(JSON.stringify(hotUpdateMainContent)); + const filename = compilation.getPath(hotUpdateMainFilename, { + hash: records.hash }); + compilation.assets[filename] = source; } + ); + + const mainTemplate = compilation.mainTemplate; + + mainTemplate.hooks.hash.tap("HotModuleReplacementPlugin", hash => { + hash.update("HotMainTemplateDecorator"); }); - parser.hooks.expression.for("module.hot").tap("HotModuleReplacementPlugin", ParserHelpers.skipTraversal); - }; - // TODO add HMR support for javascript/esm - normalModuleFactory.hooks.parser.for("javascript/auto").tap("HotModuleReplacementPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("HotModuleReplacementPlugin", handler); + mainTemplate.hooks.moduleRequire.tap( + "HotModuleReplacementPlugin", + (_, chunk, hash, varModuleId) => { + return `hotCreateRequire(${varModuleId})`; + } + ); - compilation.hooks.normalModuleLoader.tap("HotModuleReplacementPlugin", context => { - context.hot = true; - }); - }); + mainTemplate.hooks.requireExtensions.tap( + "HotModuleReplacementPlugin", + source => { + const buf = [source]; + buf.push(""); + buf.push("// __webpack_hash__"); + buf.push( + mainTemplate.requireFn + + ".h = function() { return hotCurrentHash; };" + ); + return Template.asString(buf); + } + ); + + const needChunkLoadingCode = chunk => { + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.chunks.length > 1) return true; + if (chunkGroup.getNumberOfChildren() > 0) return true; + } + return false; + }; + + mainTemplate.hooks.bootstrap.tap( + "HotModuleReplacementPlugin", + (source, chunk, hash) => { + source = mainTemplate.hooks.hotBootstrap.call(source, chunk, hash); + return Template.asString([ + source, + "", + hotInitCode + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace(/\$hash\$/g, JSON.stringify(hash)) + .replace(/\$requestTimeout\$/g, requestTimeout) + .replace( + /\/\*foreachInstalledChunks\*\//g, + needChunkLoadingCode(chunk) + ? "for(var chunkId in installedChunks)" + : `var chunkId = ${JSON.stringify(chunk.id)};` + ) + ]); + } + ); + + mainTemplate.hooks.globalHash.tap( + "HotModuleReplacementPlugin", + () => true + ); + + mainTemplate.hooks.currentHash.tap( + "HotModuleReplacementPlugin", + (_, length) => { + if (isFinite(length)) return `hotCurrentHash.substr(0, ${length})`; + else return "hotCurrentHash"; + } + ); + + mainTemplate.hooks.moduleObj.tap( + "HotModuleReplacementPlugin", + (source, chunk, hash, varModuleId) => { + return Template.asString([ + `${source},`, + `hot: hotCreateModule(${varModuleId}),`, + "parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),", + "children: []" + ]); + } + ); + + const handler = (parser, parserOptions) => { + parser.hooks.expression + .for("__webpack_hash__") + .tap( + "HotModuleReplacementPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.h()" + ) + ); + parser.hooks.evaluateTypeof + .for("__webpack_hash__") + .tap( + "HotModuleReplacementPlugin", + ParserHelpers.evaluateToString("string") + ); + parser.hooks.evaluateIdentifier.for("module.hot").tap( + { + name: "HotModuleReplacementPlugin", + before: "NodeStuffPlugin" + }, + expr => { + return ParserHelpers.evaluateToIdentifier( + "module.hot", + !!parser.state.compilation.hotUpdateChunkTemplate + )(expr); + } + ); + // TODO webpack 5: refactor this, no custom hooks + if (!parser.hooks.hotAcceptCallback) + parser.hooks.hotAcceptCallback = new SyncBailHook([ + "expression", + "requests" + ]); + if (!parser.hooks.hotAcceptWithoutCallback) + parser.hooks.hotAcceptWithoutCallback = new SyncBailHook([ + "expression", + "requests" + ]); + parser.hooks.call + .for("module.hot.accept") + .tap("HotModuleReplacementPlugin", expr => { + if (!parser.state.compilation.hotUpdateChunkTemplate) + return false; + if (expr.arguments.length >= 1) { + const arg = parser.evaluateExpression(expr.arguments[0]); + let params = []; + let requests = []; + if (arg.isString()) { + params = [arg]; + } else if (arg.isArray()) { + params = arg.items.filter(param => param.isString()); + } + if (params.length > 0) { + params.forEach((param, idx) => { + const request = param.string; + const dep = new ModuleHotAcceptDependency( + request, + param.range + ); + dep.optional = true; + dep.loc = Object.create(expr.loc); + dep.loc.index = idx; + parser.state.module.addDependency(dep); + requests.push(request); + }); + if (expr.arguments.length > 1) + parser.hooks.hotAcceptCallback.call( + expr.arguments[1], + requests + ); + else + parser.hooks.hotAcceptWithoutCallback.call(expr, requests); + } + } + }); + parser.hooks.call + .for("module.hot.decline") + .tap("HotModuleReplacementPlugin", expr => { + if (!parser.state.compilation.hotUpdateChunkTemplate) + return false; + if (expr.arguments.length === 1) { + const arg = parser.evaluateExpression(expr.arguments[0]); + let params = []; + if (arg.isString()) { + params = [arg]; + } else if (arg.isArray()) { + params = arg.items.filter(param => param.isString()); + } + params.forEach((param, idx) => { + const dep = new ModuleHotDeclineDependency( + param.string, + param.range + ); + dep.optional = true; + dep.loc = Object.create(expr.loc); + dep.loc.index = idx; + parser.state.module.addDependency(dep); + }); + } + }); + parser.hooks.expression + .for("module.hot") + .tap("HotModuleReplacementPlugin", ParserHelpers.skipTraversal); + }; + + // TODO add HMR support for javascript/esm + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("HotModuleReplacementPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("HotModuleReplacementPlugin", handler); + + compilation.hooks.normalModuleLoader.tap( + "HotModuleReplacementPlugin", + context => { + context.hot = true; + } + ); + } + ); } - }; -const hotInitCode = Template.getFunctionContent(require("./HotModuleReplacement.runtime.js")); +const hotInitCode = Template.getFunctionContent( + require("./HotModuleReplacement.runtime.js") +); diff --git a/lib/HotUpdateChunkTemplate.js b/lib/HotUpdateChunkTemplate.js index 9bdd4a855..f1c7c372b 100644 --- a/lib/HotUpdateChunkTemplate.js +++ b/lib/HotUpdateChunkTemplate.js @@ -15,20 +15,60 @@ module.exports = class HotUpdateChunkTemplate extends Tapable { super(); this.outputOptions = outputOptions || {}; this.hooks = { - modules: new SyncWaterfallHook(["source", "modules", "removedModules", "moduleTemplate", "dependencyTemplates"]), - render: new SyncWaterfallHook(["source", "modules", "removedModules", "hash", "id", "moduleTemplate", "dependencyTemplates"]), - hash: new SyncHook(["hash"]), + modules: new SyncWaterfallHook([ + "source", + "modules", + "removedModules", + "moduleTemplate", + "dependencyTemplates" + ]), + render: new SyncWaterfallHook([ + "source", + "modules", + "removedModules", + "hash", + "id", + "moduleTemplate", + "dependencyTemplates" + ]), + hash: new SyncHook(["hash"]) }; } - render(id, modules, removedModules, hash, moduleTemplate, dependencyTemplates) { + render( + id, + modules, + removedModules, + hash, + moduleTemplate, + dependencyTemplates + ) { const hotUpdateChunk = new Chunk(); hotUpdateChunk.id = id; hotUpdateChunk.setModules(modules); hotUpdateChunk.removedModules = removedModules; - const modulesSource = Template.renderChunkModules(hotUpdateChunk, () => true, moduleTemplate, dependencyTemplates); - const core = this.hooks.modules.call(modulesSource, modules, removedModules, moduleTemplate, dependencyTemplates); - const source = this.hooks.render.call(core, modules, removedModules, hash, id, moduleTemplate, dependencyTemplates); + const modulesSource = Template.renderChunkModules( + hotUpdateChunk, + () => true, + moduleTemplate, + dependencyTemplates + ); + const core = this.hooks.modules.call( + modulesSource, + modules, + removedModules, + moduleTemplate, + dependencyTemplates + ); + const source = this.hooks.render.call( + core, + modules, + removedModules, + hash, + id, + moduleTemplate, + dependencyTemplates + ); return source; } diff --git a/lib/IgnorePlugin.js b/lib/IgnorePlugin.js index d889d76f9..5cc6c62f8 100644 --- a/lib/IgnorePlugin.js +++ b/lib/IgnorePlugin.js @@ -17,7 +17,7 @@ class IgnorePlugin { * and the resource given matches the regexp. */ checkResource(resource) { - if(!this.resourceRegExp) { + if (!this.resourceRegExp) { return false; } return this.resourceRegExp.test(resource); @@ -28,7 +28,7 @@ class IgnorePlugin { * or if context matches the given regexp. */ checkContext(context) { - if(!this.contextRegExp) { + if (!this.contextRegExp) { return true; } return this.contextRegExp.test(context); @@ -42,25 +42,27 @@ class IgnorePlugin { * and "contextRegExp" have to match. */ checkResult(result) { - if(!result) { + if (!result) { return true; } - return this.checkResource(result.request) && this.checkContext(result.context); + return ( + this.checkResource(result.request) && this.checkContext(result.context) + ); } checkIgnore(result) { // check if result is ignored - if(this.checkResult(result)) { + if (this.checkResult(result)) { return null; } return result; } apply(compiler) { - compiler.hooks.normalModuleFactory.tap("IgnorePlugin", (nmf) => { + compiler.hooks.normalModuleFactory.tap("IgnorePlugin", nmf => { nmf.hooks.beforeResolve.tap("IgnorePlugin", this.checkIgnore); }); - compiler.hooks.contextModuleFactory.tap("IgnorePlugin", (cmf) => { + compiler.hooks.contextModuleFactory.tap("IgnorePlugin", cmf => { cmf.hooks.beforeResolve.tap("IgnorePlugin", this.checkIgnore); }); } diff --git a/lib/JavascriptGenerator.js b/lib/JavascriptGenerator.js index 19ac2857c..cbefeb86b 100644 --- a/lib/JavascriptGenerator.js +++ b/lib/JavascriptGenerator.js @@ -13,23 +13,41 @@ const ReplaceSource = require("webpack-sources").ReplaceSource; // TODO: remove DependencyVariables and replace them with something better class JavascriptGenerator { - generate(module, dependencyTemplates, runtimeTemplate) { const originalSource = module.originalSource(); - if(!originalSource) { + if (!originalSource) { return new RawSource("throw new Error('No source available');"); } const source = new ReplaceSource(originalSource); - this.sourceBlock(module, module, [], dependencyTemplates, source, runtimeTemplate); + this.sourceBlock( + module, + module, + [], + dependencyTemplates, + source, + runtimeTemplate + ); return source; } - sourceBlock(module, block, availableVars, dependencyTemplates, source, runtimeTemplate) { - for(const dependency of block.dependencies) { - this.sourceDependency(dependency, dependencyTemplates, source, runtimeTemplate); + sourceBlock( + module, + block, + availableVars, + dependencyTemplates, + source, + runtimeTemplate + ) { + for (const dependency of block.dependencies) { + this.sourceDependency( + dependency, + dependencyTemplates, + source, + runtimeTemplate + ); } /** @@ -39,9 +57,13 @@ class JavascriptGenerator { */ const vars = block.variables.reduce((result, value) => { const variable = this.sourceVariables( - value, availableVars, dependencyTemplates, runtimeTemplate); + value, + availableVars, + dependencyTemplates, + runtimeTemplate + ); - if(variable) { + if (variable) { result.push(variable); } @@ -54,7 +76,7 @@ class JavascriptGenerator { * it will always return an array in an array which would lead to a IIFE wrapper around * a module if we do this with an empty vars array. */ - if(vars.length > 0) { + if (vars.length > 0) { /** * Split all variables up into chunks of unique names. * e.g. imagine you have the following variable names that need to be injected: @@ -69,20 +91,25 @@ class JavascriptGenerator { * "splitVariablesInUniqueNamedChunks" splits the variables shown above up to this: * [[foo, bar, baz], [foo, some, more]] */ - const injectionVariableChunks = this.splitVariablesInUniqueNamedChunks(vars); + const injectionVariableChunks = this.splitVariablesInUniqueNamedChunks( + vars + ); // create all the beginnings of IIFEs - const functionWrapperStarts = injectionVariableChunks.map((variableChunk) => { - return this.variableInjectionFunctionWrapperStartCode( - variableChunk.map(variable => variable.name) - ); - }); + const functionWrapperStarts = injectionVariableChunks.map( + variableChunk => { + return this.variableInjectionFunctionWrapperStartCode( + variableChunk.map(variable => variable.name) + ); + } + ); // and all the ends - const functionWrapperEnds = injectionVariableChunks.map((variableChunk) => { + const functionWrapperEnds = injectionVariableChunks.map(variableChunk => { return this.variableInjectionFunctionWrapperEndCode( module, - variableChunk.map(variable => variable.expression), block + variableChunk.map(variable => variable.expression), + block ); }); @@ -93,15 +120,17 @@ class JavascriptGenerator { const varEndCode = functionWrapperEnds.reverse().join(""); // if we have anything, add it to the source - if(varStartCode && varEndCode) { + if (varStartCode && varEndCode) { const start = block.range ? block.range[0] : -10; - const end = block.range ? block.range[1] : (module.originalSource().size() + 1); + const end = block.range + ? block.range[1] + : module.originalSource().size() + 1; source.insert(start + 0.5, varStartCode); source.insert(end + 0.5, "\n/* WEBPACK VAR INJECTION */" + varEndCode); } } - for(const childBlock of block.blocks) { + for (const childBlock of block.blocks) { this.sourceBlock( module, childBlock, @@ -115,15 +144,30 @@ class JavascriptGenerator { sourceDependency(dependency, dependencyTemplates, source, runtimeTemplate) { const template = dependencyTemplates.get(dependency.constructor); - if(!template) throw new Error("No template for dependency: " + dependency.constructor.name); + if (!template) + throw new Error( + "No template for dependency: " + dependency.constructor.name + ); template.apply(dependency, source, runtimeTemplate, dependencyTemplates); } - sourceVariables(variable, availableVars, dependencyTemplates, runtimeTemplate) { + sourceVariables( + variable, + availableVars, + dependencyTemplates, + runtimeTemplate + ) { const name = variable.name; - const expr = variable.expressionSource(dependencyTemplates, runtimeTemplate); + const expr = variable.expressionSource( + dependencyTemplates, + runtimeTemplate + ); - if(availableVars.some(v => v.name === name && v.expression.source() === expr.source())) { + if ( + availableVars.some( + v => v.name === name && v.expression.source() === expr.source() + ) + ) { return; } return { @@ -143,7 +187,7 @@ class JavascriptGenerator { } contextArgument(module, block) { - if(this === block) { + if (this === block) { return module.exportsArgument; } return "this"; @@ -161,16 +205,16 @@ class JavascriptGenerator { } splitVariablesInUniqueNamedChunks(vars) { - const startState = [ - [] - ]; + const startState = [[]]; return vars.reduce((chunks, variable) => { const current = chunks[chunks.length - 1]; // check if variable with same name exists already // if so create a new chunk of variables. - const variableNameAlreadyExists = current.some(v => v.name === variable.name); + const variableNameAlreadyExists = current.some( + v => v.name === variable.name + ); - if(variableNameAlreadyExists) { + if (variableNameAlreadyExists) { // start new chunk with current variable chunks.push([variable]); } else { @@ -180,7 +224,6 @@ class JavascriptGenerator { return chunks; }, startState); } - } module.exports = JavascriptGenerator; diff --git a/lib/JavascriptModulesPlugin.js b/lib/JavascriptModulesPlugin.js index 1f0899380..6394f465f 100644 --- a/lib/JavascriptModulesPlugin.js +++ b/lib/JavascriptModulesPlugin.js @@ -11,86 +11,140 @@ const JavascriptGenerator = require("./JavascriptGenerator"); class JavascriptModulesPlugin { apply(compiler) { - compiler.hooks.compilation.tap("JavascriptModulesPlugin", (compilation, { - normalModuleFactory - }) => { - normalModuleFactory.hooks.createParser.for("javascript/auto").tap("JavascriptModulesPlugin", options => { - return new Parser(options, "auto"); - }); - normalModuleFactory.hooks.createParser.for("javascript/dynamic").tap("JavascriptModulesPlugin", options => { - return new Parser(options, "script"); - }); - normalModuleFactory.hooks.createParser.for("javascript/esm").tap("JavascriptModulesPlugin", options => { - return new Parser(options, "module"); - }); - normalModuleFactory.hooks.createGenerator.for("javascript/auto").tap("JavascriptModulesPlugin", options => { - return new JavascriptGenerator(options); - }); - normalModuleFactory.hooks.createGenerator.for("javascript/dynamic").tap("JavascriptModulesPlugin", options => { - return new JavascriptGenerator(options); - }); - normalModuleFactory.hooks.createGenerator.for("javascript/esm").tap("JavascriptModulesPlugin", options => { - return new JavascriptGenerator(options); - }); - compilation.mainTemplate.hooks.renderManifest.tap("JavascriptModulesPlugin", (result, options) => { - const chunk = options.chunk; - const hash = options.hash; - const fullHash = options.fullHash; - const outputOptions = options.outputOptions; - const moduleTemplates = options.moduleTemplates; - const dependencyTemplates = options.dependencyTemplates; + compiler.hooks.compilation.tap( + "JavascriptModulesPlugin", + (compilation, { normalModuleFactory }) => { + normalModuleFactory.hooks.createParser + .for("javascript/auto") + .tap("JavascriptModulesPlugin", options => { + return new Parser(options, "auto"); + }); + normalModuleFactory.hooks.createParser + .for("javascript/dynamic") + .tap("JavascriptModulesPlugin", options => { + return new Parser(options, "script"); + }); + normalModuleFactory.hooks.createParser + .for("javascript/esm") + .tap("JavascriptModulesPlugin", options => { + return new Parser(options, "module"); + }); + normalModuleFactory.hooks.createGenerator + .for("javascript/auto") + .tap("JavascriptModulesPlugin", options => { + return new JavascriptGenerator(options); + }); + normalModuleFactory.hooks.createGenerator + .for("javascript/dynamic") + .tap("JavascriptModulesPlugin", options => { + return new JavascriptGenerator(options); + }); + normalModuleFactory.hooks.createGenerator + .for("javascript/esm") + .tap("JavascriptModulesPlugin", options => { + return new JavascriptGenerator(options); + }); + compilation.mainTemplate.hooks.renderManifest.tap( + "JavascriptModulesPlugin", + (result, options) => { + const chunk = options.chunk; + const hash = options.hash; + const fullHash = options.fullHash; + const outputOptions = options.outputOptions; + const moduleTemplates = options.moduleTemplates; + const dependencyTemplates = options.dependencyTemplates; - let filenameTemplate; - if(chunk.filenameTemplate) - filenameTemplate = chunk.filenameTemplate; - else - filenameTemplate = outputOptions.filename; + let filenameTemplate; + if (chunk.filenameTemplate) + filenameTemplate = chunk.filenameTemplate; + else filenameTemplate = outputOptions.filename; - const useChunkHash = compilation.mainTemplate.useChunkHash(chunk); + const useChunkHash = compilation.mainTemplate.useChunkHash(chunk); - result.push({ - render: () => compilation.mainTemplate.render(hash, chunk, moduleTemplates.javascript, dependencyTemplates), - filenameTemplate, - pathOptions: { - noChunkHash: !useChunkHash, - chunk - }, - identifier: `chunk${chunk.id}`, - hash: useChunkHash ? chunk.hash : fullHash - }); - return result; - }); - compilation.mainTemplate.hooks.modules.tap("JavascriptModulesPlugin", (source, chunk, hash, moduleTemplate, dependencyTemplates) => { - return Template.renderChunkModules(chunk, () => true, moduleTemplate, dependencyTemplates, "/******/ "); - }); - compilation.chunkTemplate.hooks.renderManifest.tap("JavascriptModulesPlugin", (result, options) => { - const chunk = options.chunk; - const outputOptions = options.outputOptions; - const moduleTemplates = options.moduleTemplates; - const dependencyTemplates = options.dependencyTemplates; + result.push({ + render: () => + compilation.mainTemplate.render( + hash, + chunk, + moduleTemplates.javascript, + dependencyTemplates + ), + filenameTemplate, + pathOptions: { + noChunkHash: !useChunkHash, + chunk + }, + identifier: `chunk${chunk.id}`, + hash: useChunkHash ? chunk.hash : fullHash + }); + return result; + } + ); + compilation.mainTemplate.hooks.modules.tap( + "JavascriptModulesPlugin", + (source, chunk, hash, moduleTemplate, dependencyTemplates) => { + return Template.renderChunkModules( + chunk, + () => true, + moduleTemplate, + dependencyTemplates, + "/******/ " + ); + } + ); + compilation.chunkTemplate.hooks.renderManifest.tap( + "JavascriptModulesPlugin", + (result, options) => { + const chunk = options.chunk; + const outputOptions = options.outputOptions; + const moduleTemplates = options.moduleTemplates; + const dependencyTemplates = options.dependencyTemplates; - const filenameTemplate = outputOptions.chunkFilename; + const filenameTemplate = outputOptions.chunkFilename; - result.push({ - render: () => this.renderJavascript(compilation.chunkTemplate, chunk, moduleTemplates.javascript, dependencyTemplates), - filenameTemplate, - pathOptions: { - chunk - }, - identifier: `chunk${chunk.id}`, - hash: chunk.hash - }); + result.push({ + render: () => + this.renderJavascript( + compilation.chunkTemplate, + chunk, + moduleTemplates.javascript, + dependencyTemplates + ), + filenameTemplate, + pathOptions: { + chunk + }, + identifier: `chunk${chunk.id}`, + hash: chunk.hash + }); - return result; - }); - }); + return result; + } + ); + } + ); } renderJavascript(chunkTemplate, chunk, moduleTemplate, dependencyTemplates) { - const moduleSources = Template.renderChunkModules(chunk, m => true, moduleTemplate, dependencyTemplates); - const core = chunkTemplate.hooks.modules.call(moduleSources, chunk, moduleTemplate, dependencyTemplates); - let source = chunkTemplate.hooks.render.call(core, chunk, moduleTemplate, dependencyTemplates); - if(chunk.hasEntryModule()) { + const moduleSources = Template.renderChunkModules( + chunk, + m => true, + moduleTemplate, + dependencyTemplates + ); + const core = chunkTemplate.hooks.modules.call( + moduleSources, + chunk, + moduleTemplate, + dependencyTemplates + ); + let source = chunkTemplate.hooks.render.call( + core, + chunk, + moduleTemplate, + dependencyTemplates + ); + if (chunk.hasEntryModule()) { source = chunkTemplate.hooks.renderWithEntry.call(source, chunk); } chunk.rendered = true; diff --git a/lib/JsonGenerator.js b/lib/JsonGenerator.js index b5cd17c78..3b7c56f1a 100644 --- a/lib/JsonGenerator.js +++ b/lib/JsonGenerator.js @@ -6,25 +6,32 @@ const ConcatSource = require("webpack-sources").ConcatSource; -const stringifySafe = data => JSON.stringify(data) - .replace(/\u2028|\u2029/g, str => str === "\u2029" ? "\\u2029" : "\\u2028"); // invalid in JavaScript but valid JSON +const stringifySafe = data => + JSON.stringify(data).replace( + /\u2028|\u2029/g, + str => (str === "\u2029" ? "\\u2029" : "\\u2028") + ); // invalid in JavaScript but valid JSON class JsonGenerator { generate(module, dependencyTemplates, runtimeTemplate) { const source = new ConcatSource(); const data = module.buildInfo.jsonData; - if(Array.isArray(module.buildMeta.providedExports) && !module.isUsed("default")) { + if ( + Array.isArray(module.buildMeta.providedExports) && + !module.isUsed("default") + ) { // Only some exports are used: We can optimize here, by only generating a part of the JSON const reducedJson = {}; - for(const exportName of module.buildMeta.providedExports) { - if(exportName === "default") - continue; + for (const exportName of module.buildMeta.providedExports) { + if (exportName === "default") continue; const used = module.isUsed(exportName); - if(used) { + if (used) { reducedJson[used] = data[exportName]; } } - source.add(`${module.moduleArgument}.exports = ${stringifySafe(reducedJson)};`); + source.add( + `${module.moduleArgument}.exports = ${stringifySafe(reducedJson)};` + ); } else { source.add(`${module.moduleArgument}.exports = ${stringifySafe(data)};`); } diff --git a/lib/JsonModulesPlugin.js b/lib/JsonModulesPlugin.js index c32d13943..20b8a034c 100644 --- a/lib/JsonModulesPlugin.js +++ b/lib/JsonModulesPlugin.js @@ -9,16 +9,21 @@ const JsonGenerator = require("./JsonGenerator"); class JsonModulesPlugin { apply(compiler) { - compiler.hooks.compilation.tap("JsonModulesPlugin", (compilation, { - normalModuleFactory - }) => { - normalModuleFactory.hooks.createParser.for("json").tap("JsonModulesPlugin", () => { - return new JsonParser(); - }); - normalModuleFactory.hooks.createGenerator.for("json").tap("JsonModulesPlugin", () => { - return new JsonGenerator(); - }); - }); + compiler.hooks.compilation.tap( + "JsonModulesPlugin", + (compilation, { normalModuleFactory }) => { + normalModuleFactory.hooks.createParser + .for("json") + .tap("JsonModulesPlugin", () => { + return new JsonParser(); + }); + normalModuleFactory.hooks.createGenerator + .for("json") + .tap("JsonModulesPlugin", () => { + return new JsonGenerator(); + }); + } + ); } } diff --git a/lib/JsonParser.js b/lib/JsonParser.js index 21c1de96b..0c67ff48d 100644 --- a/lib/JsonParser.js +++ b/lib/JsonParser.js @@ -15,7 +15,7 @@ class JsonParser { const data = JSON.parse(source); state.module.buildInfo.jsonData = data; state.module.buildMeta.exportsType = "named"; - if(typeof data === "object" && data) + if (typeof data === "object" && data) state.module.addDependency(new JsonExportsDependency(Object.keys(data))); state.module.addDependency(new JsonExportsDependency(["default"])); return state; diff --git a/lib/LibManifestPlugin.js b/lib/LibManifestPlugin.js index d05e15ad2..7faf79354 100644 --- a/lib/LibManifestPlugin.js +++ b/lib/LibManifestPlugin.js @@ -13,50 +13,65 @@ class LibManifestPlugin { } apply(compiler) { - compiler.hooks.emit.tapAsync("LibManifestPlugin", (compilation, callback) => { - asyncLib.forEach(compilation.chunks, (chunk, callback) => { - if(!chunk.isOnlyInitial()) { - callback(); - return; - } - const targetPath = compilation.getPath(this.options.path, { - hash: compilation.hash, - chunk - }); - const name = this.options.name && compilation.getPath(this.options.name, { - hash: compilation.hash, - chunk - }); - const manifest = { - name, - type: this.options.type, - content: Array.from(chunk.modulesIterable, module => { - if(module.libIdent) { - const ident = module.libIdent({ - context: this.options.context || compiler.options.context - }); - if(ident) { - return { - ident, - data: { - id: module.id, - buildMeta: module.buildMeta - } - }; - } + compiler.hooks.emit.tapAsync( + "LibManifestPlugin", + (compilation, callback) => { + asyncLib.forEach( + compilation.chunks, + (chunk, callback) => { + if (!chunk.isOnlyInitial()) { + callback(); + return; } - }).filter(Boolean).reduce((obj, item) => { - obj[item.ident] = item.data; - return obj; - }, Object.create(null)) - }; - const content = Buffer.from(JSON.stringify(manifest), "utf8"); - compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => { - if(err) return callback(err); - compiler.outputFileSystem.writeFile(targetPath, content, callback); - }); - }, callback); - }); + const targetPath = compilation.getPath(this.options.path, { + hash: compilation.hash, + chunk + }); + const name = + this.options.name && + compilation.getPath(this.options.name, { + hash: compilation.hash, + chunk + }); + const manifest = { + name, + type: this.options.type, + content: Array.from(chunk.modulesIterable, module => { + if (module.libIdent) { + const ident = module.libIdent({ + context: this.options.context || compiler.options.context + }); + if (ident) { + return { + ident, + data: { + id: module.id, + buildMeta: module.buildMeta + } + }; + } + } + }) + .filter(Boolean) + .reduce((obj, item) => { + obj[item.ident] = item.data; + return obj; + }, Object.create(null)) + }; + const content = Buffer.from(JSON.stringify(manifest), "utf8"); + compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => { + if (err) return callback(err); + compiler.outputFileSystem.writeFile( + targetPath, + content, + callback + ); + }); + }, + callback + ); + } + ); } } module.exports = LibManifestPlugin; diff --git a/lib/LibraryTemplatePlugin.js b/lib/LibraryTemplatePlugin.js index d89d868e1..88c342cff 100644 --- a/lib/LibraryTemplatePlugin.js +++ b/lib/LibraryTemplatePlugin.js @@ -6,26 +6,30 @@ const SetVarMainTemplatePlugin = require("./SetVarMainTemplatePlugin"); -const accessorToObjectAccess = (accessor) => { - return accessor.map((a) => { - return `[${JSON.stringify(a)}]`; - }).join(""); +const accessorToObjectAccess = accessor => { + return accessor + .map(a => { + return `[${JSON.stringify(a)}]`; + }) + .join(""); }; const accessorAccess = (base, accessor, joinWith) => { accessor = [].concat(accessor); - return accessor.map((a, idx) => { - a = base ? - base + accessorToObjectAccess(accessor.slice(0, idx + 1)) : - accessor[0] + accessorToObjectAccess(accessor.slice(1, idx + 1)); - if(idx === accessor.length - 1) return a; - if(idx === 0 && typeof base === "undefined") return `${a} = typeof ${a} === "object" ? ${a} : {}`; - return `${a} = ${a} || {}`; - }).join(joinWith || "; "); + return accessor + .map((a, idx) => { + a = base + ? base + accessorToObjectAccess(accessor.slice(0, idx + 1)) + : accessor[0] + accessorToObjectAccess(accessor.slice(1, idx + 1)); + if (idx === accessor.length - 1) return a; + if (idx === 0 && typeof base === "undefined") + return `${a} = typeof ${a} === "object" ? ${a} : {}`; + return `${a} = ${a} || {}`; + }) + .join(joinWith || "; "); }; class LibraryTemplatePlugin { - constructor(name, target, umdNamedDefine, auxiliaryComment, exportProperty) { this.name = name; this.target = target; @@ -35,37 +39,54 @@ class LibraryTemplatePlugin { } apply(compiler) { - compiler.hooks.thisCompilation.tap("LibraryTemplatePlugin", (compilation) => { - if(this.exportProperty) { + compiler.hooks.thisCompilation.tap("LibraryTemplatePlugin", compilation => { + if (this.exportProperty) { var ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin"); - new ExportPropertyMainTemplatePlugin(this.exportProperty).apply(compilation); + new ExportPropertyMainTemplatePlugin(this.exportProperty).apply( + compilation + ); } - switch(this.target) { + switch (this.target) { case "var": - new SetVarMainTemplatePlugin(`var ${accessorAccess(false, this.name)}`).apply(compilation); + new SetVarMainTemplatePlugin( + `var ${accessorAccess(false, this.name)}` + ).apply(compilation); break; case "assign": - new SetVarMainTemplatePlugin(accessorAccess(undefined, this.name)).apply(compilation); + new SetVarMainTemplatePlugin( + accessorAccess(undefined, this.name) + ).apply(compilation); break; case "this": case "self": case "window": - if(this.name) - new SetVarMainTemplatePlugin(accessorAccess(this.target, this.name)).apply(compilation); + if (this.name) + new SetVarMainTemplatePlugin( + accessorAccess(this.target, this.name) + ).apply(compilation); else new SetVarMainTemplatePlugin(this.target, true).apply(compilation); break; case "global": - if(this.name) - new SetVarMainTemplatePlugin(accessorAccess(compilation.runtimeTemplate.outputOptions.globalObject, this.name)).apply(compilation); + if (this.name) + new SetVarMainTemplatePlugin( + accessorAccess( + compilation.runtimeTemplate.outputOptions.globalObject, + this.name + ) + ).apply(compilation); else - new SetVarMainTemplatePlugin(compilation.runtimeTemplate.outputOptions.globalObject, true).apply(compilation); + new SetVarMainTemplatePlugin( + compilation.runtimeTemplate.outputOptions.globalObject, + true + ).apply(compilation); break; case "commonjs": - if(this.name) - new SetVarMainTemplatePlugin(accessorAccess("exports", this.name)).apply(compilation); - else - new SetVarMainTemplatePlugin("exports", true).apply(compilation); + if (this.name) + new SetVarMainTemplatePlugin( + accessorAccess("exports", this.name) + ).apply(compilation); + else new SetVarMainTemplatePlugin("exports", true).apply(compilation); break; case "commonjs2": case "commonjs-module": diff --git a/lib/LoaderOptionsPlugin.js b/lib/LoaderOptionsPlugin.js index 89a406e7a..1493df37b 100644 --- a/lib/LoaderOptionsPlugin.js +++ b/lib/LoaderOptionsPlugin.js @@ -13,29 +13,38 @@ class LoaderOptionsPlugin { constructor(options) { validateOptions(schema, options || {}, "Loader Options Plugin"); - if(typeof options !== "object") options = {}; - if(!options.test) options.test = { - test: () => true - }; + if (typeof options !== "object") options = {}; + if (!options.test) + options.test = { + test: () => true + }; this.options = options; } apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("LoaderOptionsPlugin", (compilation) => { - compilation.hooks.normalModuleLoader.tap("LoaderOptionsPlugin", (context, module) => { - const resource = module.resource; - if(!resource) return; - const i = resource.indexOf("?"); - if(ModuleFilenameHelpers.matchObject(options, i < 0 ? resource : resource.substr(0, i))) { - for(const key of Object.keys(options)) { - if(key === "include" || key === "exclude" || key === "test") { - continue; + compiler.hooks.compilation.tap("LoaderOptionsPlugin", compilation => { + compilation.hooks.normalModuleLoader.tap( + "LoaderOptionsPlugin", + (context, module) => { + const resource = module.resource; + if (!resource) return; + const i = resource.indexOf("?"); + if ( + ModuleFilenameHelpers.matchObject( + options, + i < 0 ? resource : resource.substr(0, i) + ) + ) { + for (const key of Object.keys(options)) { + if (key === "include" || key === "exclude" || key === "test") { + continue; + } + context[key] = options[key]; } - context[key] = options[key]; } } - }); + ); }); } } diff --git a/lib/LoaderTargetPlugin.js b/lib/LoaderTargetPlugin.js index 12dd47d13..99ffbc997 100644 --- a/lib/LoaderTargetPlugin.js +++ b/lib/LoaderTargetPlugin.js @@ -10,10 +10,13 @@ class LoaderTargetPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("LoaderTargetPlugin", (compilation) => { - compilation.hooks.normalModuleLoader.tap("LoaderTargetPlugin", (loaderContext) => { - loaderContext.target = this.target; - }); + compiler.hooks.compilation.tap("LoaderTargetPlugin", compilation => { + compilation.hooks.normalModuleLoader.tap( + "LoaderTargetPlugin", + loaderContext => { + loaderContext.target = this.target; + } + ); }); } } diff --git a/lib/MainTemplate.js b/lib/MainTemplate.js index 1aeaa6267..1fdbf8714 100644 --- a/lib/MainTemplate.js +++ b/lib/MainTemplate.js @@ -36,19 +36,58 @@ module.exports = class MainTemplate extends Tapable { this.outputOptions = outputOptions || {}; this.hooks = { renderManifest: new SyncWaterfallHook(["result", "options"]), - modules: new SyncWaterfallHook(["modules", "chunk", "hash", "moduleTemplate", "dependencyTemplates"]), - moduleObj: new SyncWaterfallHook(["source", "chunk", "hash", "moduleIdExpression"]), - requireEnsure: new SyncWaterfallHook(["source", "chunk", "hash", "chunkIdExpression"]), - bootstrap: new SyncWaterfallHook(["source", "chunk", "hash", "moduleTemplate", "dependencyTemplates"]), + modules: new SyncWaterfallHook([ + "modules", + "chunk", + "hash", + "moduleTemplate", + "dependencyTemplates" + ]), + moduleObj: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleIdExpression" + ]), + requireEnsure: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "chunkIdExpression" + ]), + bootstrap: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleTemplate", + "dependencyTemplates" + ]), localVars: new SyncWaterfallHook(["source", "chunk", "hash"]), require: new SyncWaterfallHook(["source", "chunk", "hash"]), requireExtensions: new SyncWaterfallHook(["source", "chunk", "hash"]), beforeStartup: new SyncWaterfallHook(["source", "chunk", "hash"]), startup: new SyncWaterfallHook(["source", "chunk", "hash"]), - render: new SyncWaterfallHook(["source", "chunk", "hash", "moduleTemplate", "dependencyTemplates"]), + render: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleTemplate", + "dependencyTemplates" + ]), renderWithEntry: new SyncWaterfallHook(["source", "chunk", "hash"]), - moduleRequire: new SyncWaterfallHook(["source", "chunk", "hash", "moduleIdExpression"]), - addModule: new SyncWaterfallHook(["source", "chunk", "hash", "moduleIdExpression", "moduleExpression"]), + moduleRequire: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleIdExpression" + ]), + addModule: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleIdExpression", + "moduleExpression" + ]), currentHash: new SyncWaterfallHook(["source", "requestedLength"]), assetPath: new SyncWaterfallHook(["path", "options"]), hash: new SyncHook(["hash"]), @@ -62,23 +101,42 @@ module.exports = class MainTemplate extends Tapable { }; this.hooks.startup.tap("MainTemplate", (source, chunk, hash) => { const buf = []; - if(chunk.entryModule) { + if (chunk.entryModule) { buf.push("// Load entry module and return exports"); - buf.push(`return ${this.renderRequireFunctionForModule(hash, chunk, JSON.stringify(chunk.entryModule.id))}(${this.requireFn}.s = ${JSON.stringify(chunk.entryModule.id)});`); + buf.push( + `return ${this.renderRequireFunctionForModule( + hash, + chunk, + JSON.stringify(chunk.entryModule.id) + )}(${this.requireFn}.s = ${JSON.stringify(chunk.entryModule.id)});` + ); } return Template.asString(buf); }); - this.hooks.render.tap("MainTemplate", (bootstrapSource, chunk, hash, moduleTemplate, dependencyTemplates) => { - const source = new ConcatSource(); - source.add("/******/ (function(modules) { // webpackBootstrap\n"); - source.add(new PrefixSource("/******/", bootstrapSource)); - source.add("/******/ })\n"); - source.add("/************************************************************************/\n"); - source.add("/******/ ("); - source.add(this.hooks.modules.call(new RawSource(""), chunk, hash, moduleTemplate, dependencyTemplates)); - source.add(")"); - return source; - }); + this.hooks.render.tap( + "MainTemplate", + (bootstrapSource, chunk, hash, moduleTemplate, dependencyTemplates) => { + const source = new ConcatSource(); + source.add("/******/ (function(modules) { // webpackBootstrap\n"); + source.add(new PrefixSource("/******/", bootstrapSource)); + source.add("/******/ })\n"); + source.add( + "/************************************************************************/\n" + ); + source.add("/******/ ("); + source.add( + this.hooks.modules.call( + new RawSource(""), + chunk, + hash, + moduleTemplate, + dependencyTemplates + ) + ); + source.add(")"); + return source; + } + ); this.hooks.localVars.tap("MainTemplate", (source, chunk, hash) => { return Template.asString([ source, @@ -98,23 +156,35 @@ module.exports = class MainTemplate extends Tapable { Template.indent(this.hooks.moduleObj.call("", chunk, hash, "moduleId")), "};", "", - Template.asString(outputOptions.strictModuleExceptionHandling ? [ - "// Execute the module function", - "var threw = true;", - "try {", - Template.indent([ - `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule(hash, chunk, "moduleId")});`, - "threw = false;" - ]), - "} finally {", - Template.indent([ - "if(threw) delete installedModules[moduleId];" - ]), - "}" - ] : [ - "// Execute the module function", - `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule(hash, chunk, "moduleId")});`, - ]), + Template.asString( + outputOptions.strictModuleExceptionHandling + ? [ + "// Execute the module function", + "var threw = true;", + "try {", + Template.indent([ + `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule( + hash, + chunk, + "moduleId" + )});`, + "threw = false;" + ]), + "} finally {", + Template.indent([ + "if(threw) delete installedModules[moduleId];" + ]), + "}" + ] + : [ + "// Execute the module function", + `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule( + hash, + chunk, + "moduleId" + )});` + ] + ), "", "// Flag the module as loaded", "module.l = true;", @@ -123,23 +193,26 @@ module.exports = class MainTemplate extends Tapable { "return module.exports;" ]); }); - this.hooks.moduleObj.tap("MainTemplate", (source, chunk, hash, varModuleId) => { - return Template.asString([ - "i: moduleId,", - "l: false,", - "exports: {}" - ]); - }); + this.hooks.moduleObj.tap( + "MainTemplate", + (source, chunk, hash, varModuleId) => { + return Template.asString(["i: moduleId,", "l: false,", "exports: {}"]); + } + ); this.hooks.requireExtensions.tap("MainTemplate", (source, chunk, hash) => { const buf = []; const chunkMaps = chunk.getChunkMaps(); // Check if there are non initial chunks which need to be imported using require-ensure - if(Object.keys(chunkMaps.hash).length) { + if (Object.keys(chunkMaps.hash).length) { buf.push("// This file contains only the entry chunk."); buf.push("// The chunk loading function for additional chunks"); buf.push(`${this.requireFn}.e = function requireEnsure(chunkId) {`); buf.push(Template.indent("var promises = [];")); - buf.push(Template.indent(this.hooks.requireEnsure.call("", chunk, hash, "chunkId"))); + buf.push( + Template.indent( + this.hooks.requireEnsure.call("", chunk, hash, "chunkId") + ) + ); buf.push(Template.indent("return Promise.all(promises);")); buf.push("};"); } @@ -154,46 +227,58 @@ module.exports = class MainTemplate extends Tapable { buf.push(""); buf.push("// define getter function for harmony exports"); buf.push(`${this.requireFn}.d = function(exports, name, getter) {`); - buf.push(Template.indent([ - `if(!${this.requireFn}.o(exports, name)) {`, + buf.push( Template.indent([ - "Object.defineProperty(exports, name, {", + `if(!${this.requireFn}.o(exports, name)) {`, Template.indent([ - "configurable: false,", - "enumerable: true,", - "get: getter" + "Object.defineProperty(exports, name, {", + Template.indent([ + "configurable: false,", + "enumerable: true,", + "get: getter" + ]), + "});" ]), - "});" - ]), - "}" - ])); + "}" + ]) + ); buf.push("};"); buf.push(""); buf.push("// define __esModule on exports"); buf.push(`${this.requireFn}.r = function(exports) {`); - buf.push(Template.indent([ - "Object.defineProperty(exports, '__esModule', { value: true });" - ])); + buf.push( + Template.indent([ + "Object.defineProperty(exports, '__esModule', { value: true });" + ]) + ); buf.push("};"); buf.push(""); - buf.push("// getDefaultExport function for compatibility with non-harmony modules"); + buf.push( + "// getDefaultExport function for compatibility with non-harmony modules" + ); buf.push(this.requireFn + ".n = function(module) {"); - buf.push(Template.indent([ - "var getter = module && module.__esModule ?", + buf.push( Template.indent([ - "function getDefault() { return module['default']; } :", - "function getModuleExports() { return module; };" - ]), - `${this.requireFn}.d(getter, 'a', getter);`, - "return getter;" - ])); + "var getter = module && module.__esModule ?", + Template.indent([ + "function getDefault() { return module['default']; } :", + "function getModuleExports() { return module; };" + ]), + `${this.requireFn}.d(getter, 'a', getter);`, + "return getter;" + ]) + ); buf.push("};"); buf.push(""); buf.push("// Object.prototype.hasOwnProperty.call"); - buf.push(`${this.requireFn}.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };`); + buf.push( + `${ + this.requireFn + }.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };` + ); const publicPath = this.getPublicPath({ hash: hash @@ -217,7 +302,15 @@ module.exports = class MainTemplate extends Tapable { render(hash, chunk, moduleTemplate, dependencyTemplates) { const buf = []; - buf.push(this.hooks.bootstrap.call("", chunk, hash, moduleTemplate, dependencyTemplates)); + buf.push( + this.hooks.bootstrap.call( + "", + chunk, + hash, + moduleTemplate, + dependencyTemplates + ) + ); buf.push(this.hooks.localVars.call("", chunk, hash)); buf.push(""); buf.push("// The require function"); @@ -225,34 +318,65 @@ module.exports = class MainTemplate extends Tapable { buf.push(Template.indent(this.hooks.require.call("", chunk, hash))); buf.push("}"); buf.push(""); - buf.push(Template.asString(this.hooks.requireExtensions.call("", chunk, hash))); + buf.push( + Template.asString(this.hooks.requireExtensions.call("", chunk, hash)) + ); buf.push(""); buf.push(Template.asString(this.hooks.beforeStartup.call("", chunk, hash))); buf.push(Template.asString(this.hooks.startup.call("", chunk, hash))); - let source = this.hooks.render.call(new OriginalSource(Template.prefix(buf, " \t") + "\n", "webpack/bootstrap"), chunk, hash, moduleTemplate, dependencyTemplates); - if(chunk.hasEntryModule()) { + let source = this.hooks.render.call( + new OriginalSource( + Template.prefix(buf, " \t") + "\n", + "webpack/bootstrap" + ), + chunk, + hash, + moduleTemplate, + dependencyTemplates + ); + if (chunk.hasEntryModule()) { source = this.hooks.renderWithEntry.call(source, chunk, hash); } - if(!source) throw new Error("Compiler error: MainTemplate plugin 'render' should return something"); + if (!source) + throw new Error( + "Compiler error: MainTemplate plugin 'render' should return something" + ); chunk.rendered = true; return new ConcatSource(source, ";"); } renderRequireFunctionForModule(hash, chunk, varModuleId) { - return this.hooks.moduleRequire.call(this.requireFn, chunk, hash, varModuleId); + return this.hooks.moduleRequire.call( + this.requireFn, + chunk, + hash, + varModuleId + ); } renderAddModule(hash, chunk, varModuleId, varModule) { - return this.hooks.addModule.call(`modules[${varModuleId}] = ${varModule};`, chunk, hash, varModuleId, varModule); + return this.hooks.addModule.call( + `modules[${varModuleId}] = ${varModule};`, + chunk, + hash, + varModuleId, + varModule + ); } renderCurrentHashCode(hash, length) { length = length || Infinity; - return this.hooks.currentHash.call(JSON.stringify(hash.substr(0, length)), length); + return this.hooks.currentHash.call( + JSON.stringify(hash.substr(0, length)), + length + ); } getPublicPath(options) { - return this.hooks.assetPath.call(this.outputOptions.publicPath || "", options); + return this.hooks.assetPath.call( + this.outputOptions.publicPath || "", + options + ); } getAssetPath(path, options) { diff --git a/lib/Module.js b/lib/Module.js index f4d82bf82..afd38e5b1 100644 --- a/lib/Module.js +++ b/lib/Module.js @@ -24,7 +24,6 @@ const sortByDebugId = (a, b) => { }; class Module extends DependenciesBlock { - constructor(type, context = null) { super(); this.type = type; @@ -71,11 +70,11 @@ class Module extends DependenciesBlock { } get exportsArgument() { - return this.buildInfo && this.buildInfo.exportsArgument || "exports"; + return (this.buildInfo && this.buildInfo.exportsArgument) || "exports"; } get moduleArgument() { - return this.buildInfo && this.buildInfo.moduleArgument || "module"; + return (this.buildInfo && this.buildInfo.moduleArgument) || "module"; } disconnect() { @@ -115,14 +114,13 @@ class Module extends DependenciesBlock { } addChunk(chunk) { - if(this._chunks.has(chunk)) - return false; + if (this._chunks.has(chunk)) return false; this._chunks.add(chunk); return true; } removeChunk(chunk) { - if(this._chunks.delete(chunk)) { + if (this._chunks.delete(chunk)) { chunk.removeModule(this); return true; } @@ -134,15 +132,17 @@ class Module extends DependenciesBlock { } isEntryModule() { - for(const chunk of this._chunks) { - if(chunk.entryModule === this) - return true; + for (const chunk of this._chunks) { + if (chunk.entryModule === this) return true; } return false; } get optional() { - return this.reasons.length > 0 && this.reasons.every(r => r.dependency && r.dependency.optional); + return ( + this.reasons.length > 0 && + this.reasons.every(r => r.dependency && r.dependency.optional) + ); } getChunks() { @@ -158,16 +158,17 @@ class Module extends DependenciesBlock { } hasEqualsChunks(otherModule) { - if(this._chunks.size !== otherModule._chunks.size) return false; + if (this._chunks.size !== otherModule._chunks.size) return false; this._chunks.sortWith(sortByDebugId); otherModule._chunks.sortWith(sortByDebugId); const a = this._chunks[Symbol.iterator](); const b = otherModule._chunks[Symbol.iterator](); - while(true) { // eslint-disable-line + while (true) { + // eslint-disable-line const aItem = a.next(); const bItem = b.next(); - if(aItem.done) return true; - if(aItem.value !== bItem.value) return false; + if (aItem.done) return true; + if (aItem.value !== bItem.value) return false; } } @@ -176,9 +177,9 @@ class Module extends DependenciesBlock { } removeReason(module, dependency) { - for(let i = 0; i < this.reasons.length; i++) { + for (let i = 0; i < this.reasons.length; i++) { let r = this.reasons[i]; - if(r.module === module && r.dependency === dependency) { + if (r.module === module && r.dependency === dependency) { this.reasons.splice(i, 1); return true; } @@ -187,14 +188,13 @@ class Module extends DependenciesBlock { } hasReasonForChunk(chunk) { - if(this._rewriteChunkInReasons) { - for(const operation of this._rewriteChunkInReasons) + if (this._rewriteChunkInReasons) { + for (const operation of this._rewriteChunkInReasons) this._doRewriteChunkInReasons(operation.oldChunk, operation.newChunks); this._rewriteChunkInReasons = undefined; } - for(let i = 0; i < this.reasons.length; i++) { - if(this.reasons[i].hasChunk(chunk)) - return true; + for (let i = 0; i < this.reasons.length; i++) { + if (this.reasons[i].hasChunk(chunk)) return true; } return false; } @@ -205,7 +205,7 @@ class Module extends DependenciesBlock { rewriteChunkInReasons(oldChunk, newChunks) { // This is expensive. Delay operation until we really need the data - if(this._rewriteChunkInReasons === undefined) + if (this._rewriteChunkInReasons === undefined) this._rewriteChunkInReasons = []; this._rewriteChunkInReasons.push({ oldChunk, @@ -214,33 +214,35 @@ class Module extends DependenciesBlock { } _doRewriteChunkInReasons(oldChunk, newChunks) { - for(let i = 0; i < this.reasons.length; i++) { + for (let i = 0; i < this.reasons.length; i++) { this.reasons[i].rewriteChunks(oldChunk, newChunks); } } isUsed(exportName) { - if(!exportName) return this.used !== false; - if(this.used === null || this.usedExports === null) return exportName; - if(!this.used) return false; - if(!this.usedExports) return false; - if(this.usedExports === true) return exportName; + if (!exportName) return this.used !== false; + if (this.used === null || this.usedExports === null) return exportName; + if (!this.used) return false; + if (!this.usedExports) return false; + if (this.usedExports === true) return exportName; let idx = this.usedExports.indexOf(exportName); - if(idx < 0) return false; + if (idx < 0) return false; // Mangle export name if possible - if(this.isProvided(exportName)) { - if(this.buildMeta.exportsType === "namespace") + if (this.isProvided(exportName)) { + if (this.buildMeta.exportsType === "namespace") return Template.numberToIdentifer(idx); - else if(this.buildMeta.exportsType === "named" && !this.usedExports.includes("default")) + else if ( + this.buildMeta.exportsType === "named" && + !this.usedExports.includes("default") + ) return Template.numberToIdentifer(idx); } return exportName; } isProvided(exportName) { - if(!Array.isArray(this.buildMeta.providedExports)) - return null; + if (!Array.isArray(this.buildMeta.providedExports)) return null; return this.buildMeta.providedExports.includes(exportName); } @@ -260,15 +262,14 @@ class Module extends DependenciesBlock { sortItems(sortChunks) { super.sortItems(); - if(sortChunks) - this._chunks.sort(); + if (sortChunks) this._chunks.sort(); this.reasons.sort((a, b) => { - if(a.module === b.module) return 0; - if(!a.module) return -1; - if(!b.module) return 1; + if (a.module === b.module) return 0; + if (!a.module) return -1; + if (!b.module) return 1; return sortById(a.module, b.module); }); - if(Array.isArray(this.usedExports)) { + if (Array.isArray(this.usedExports)) { this.usedExports.sort(); } } @@ -326,7 +327,7 @@ Object.defineProperty(Module.prototype, "meta", { }, "Module.meta was renamed to Module.buildMeta"), set: util.deprecate(function(value) { this.buildMeta = value; - }, "Module.meta was renamed to Module.buildMeta"), + }, "Module.meta was renamed to Module.buildMeta") }); Module.prototype.identifier = null; diff --git a/lib/ModuleBuildError.js b/lib/ModuleBuildError.js index 2e63eaab0..00efad164 100644 --- a/lib/ModuleBuildError.js +++ b/lib/ModuleBuildError.js @@ -13,20 +13,20 @@ class ModuleBuildError extends WebpackError { this.name = "ModuleBuildError"; this.message = "Module build failed: "; - if(err !== null && typeof err === "object") { - if(typeof err.stack === "string" && err.stack) { + if (err !== null && typeof err === "object") { + if (typeof err.stack === "string" && err.stack) { var stack = cutOffLoaderExecution(err.stack); - if(!err.hideStack) { + if (!err.hideStack) { this.message += stack; } else { this.details = stack; - if(typeof err.message === "string" && err.message) { + if (typeof err.message === "string" && err.message) { this.message += err.message; } else { this.message += err; } } - } else if(typeof err.message === "string" && err.message) { + } else if (typeof err.message === "string" && err.message) { this.message += err.message; } else { this.message += err; diff --git a/lib/ModuleDependencyError.js b/lib/ModuleDependencyError.js index e02b2e6e6..9133e1445 100644 --- a/lib/ModuleDependencyError.js +++ b/lib/ModuleDependencyError.js @@ -13,7 +13,10 @@ module.exports = class ModuleDependencyError extends WebpackError { this.name = "ModuleDependencyError"; this.message = `${formatLocation(loc)} ${err.message}`; - this.details = err.stack.split("\n").slice(1).join("\n"); + this.details = err.stack + .split("\n") + .slice(1) + .join("\n"); this.origin = this.module = module; this.error = err; diff --git a/lib/ModuleDependencyWarning.js b/lib/ModuleDependencyWarning.js index ea0c7ceda..395fbd5a1 100644 --- a/lib/ModuleDependencyWarning.js +++ b/lib/ModuleDependencyWarning.js @@ -13,7 +13,10 @@ module.exports = class ModuleDependencyWarning extends WebpackError { this.name = "ModuleDependencyWarning"; this.message = `${formatLocation(loc)} ${err.message}`; - this.details = err.stack.split("\n").slice(1).join("\n"); + this.details = err.stack + .split("\n") + .slice(1) + .join("\n"); this.origin = this.module = module; this.error = err; diff --git a/lib/ModuleError.js b/lib/ModuleError.js index a0c8cfc9c..234971bb6 100644 --- a/lib/ModuleError.js +++ b/lib/ModuleError.js @@ -13,9 +13,13 @@ class ModuleError extends WebpackError { this.name = "ModuleError"; this.module = module; - this.message = err && typeof err === "object" && err.message ? err.message : err; + this.message = + err && typeof err === "object" && err.message ? err.message : err; this.error = err; - this.details = err && typeof err === "object" && err.stack ? cleanUp(err.stack, this.message) : undefined; + this.details = + err && typeof err === "object" && err.stack + ? cleanUp(err.stack, this.message) + : undefined; Error.captureStackTrace(this, this.constructor); } diff --git a/lib/ModuleFilenameHelpers.js b/lib/ModuleFilenameHelpers.js index 3da9a63b5..5333b80ea 100644 --- a/lib/ModuleFilenameHelpers.js +++ b/lib/ModuleFilenameHelpers.js @@ -48,25 +48,31 @@ const getHash = str => { }; const asRegExp = test => { - if(typeof test === "string") test = new RegExp("^" + test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")); + if (typeof test === "string") + test = new RegExp("^" + test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")); return test; }; ModuleFilenameHelpers.createFilename = (module, options, requestShortener) => { - const opts = Object.assign({ - namespace: "", - moduleFilenameTemplate: "" - }, typeof options === "object" ? options : { - moduleFilenameTemplate: options - }); + const opts = Object.assign( + { + namespace: "", + moduleFilenameTemplate: "" + }, + typeof options === "object" + ? options + : { + moduleFilenameTemplate: options + } + ); let absoluteResourcePath; let hash; let identifier; let moduleId; let shortIdentifier; - if(module === undefined) module = ""; - if(typeof module === "string") { + if (module === undefined) module = ""; + if (typeof module === "string") { shortIdentifier = requestShortener.shorten(module); identifier = shortIdentifier; moduleId = ""; @@ -76,7 +82,10 @@ ModuleFilenameHelpers.createFilename = (module, options, requestShortener) => { shortIdentifier = module.readableIdentifier(requestShortener); identifier = requestShortener.shorten(module.identifier()); moduleId = module.id; - absoluteResourcePath = module.identifier().split("!").pop(); + absoluteResourcePath = module + .identifier() + .split("!") + .pop(); hash = getHash(identifier); } const resource = shortIdentifier.split("!").pop(); @@ -84,7 +93,7 @@ ModuleFilenameHelpers.createFilename = (module, options, requestShortener) => { const allLoaders = getBefore(identifier, "!"); const query = getAfter(resource, "?"); const resourcePath = resource.substr(0, resource.length - query.length); - if(typeof opts.moduleFilenameTemplate === "function") { + if (typeof opts.moduleFilenameTemplate === "function") { return opts.moduleFilenameTemplate({ identifier: identifier, shortIdentifier: shortIdentifier, @@ -103,7 +112,10 @@ ModuleFilenameHelpers.createFilename = (module, options, requestShortener) => { .replace(ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE, shortIdentifier) .replace(ModuleFilenameHelpers.REGEXP_RESOURCE, resource) .replace(ModuleFilenameHelpers.REGEXP_RESOURCE_PATH, resourcePath) - .replace(ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH, absoluteResourcePath) + .replace( + ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH, + absoluteResourcePath + ) .replace(ModuleFilenameHelpers.REGEXP_ALL_LOADERS, allLoaders) .replace(ModuleFilenameHelpers.REGEXP_LOADERS, loaders) .replace(ModuleFilenameHelpers.REGEXP_QUERY, query) @@ -116,28 +128,27 @@ ModuleFilenameHelpers.replaceDuplicates = (array, fn, comparator) => { const countMap = Object.create(null); const posMap = Object.create(null); array.forEach((item, idx) => { - countMap[item] = (countMap[item] || []); + countMap[item] = countMap[item] || []; countMap[item].push(idx); posMap[item] = 0; }); - if(comparator) { + if (comparator) { Object.keys(countMap).forEach(item => { countMap[item].sort(comparator); }); } return array.map((item, i) => { - if(countMap[item].length > 1) { - if(comparator && countMap[item][0] === i) - return item; + if (countMap[item].length > 1) { + if (comparator && countMap[item][0] === i) return item; return fn(item, i, posMap[item]++); } else return item; }); }; ModuleFilenameHelpers.matchPart = (str, test) => { - if(!test) return true; + if (!test) return true; test = asRegExp(test); - if(Array.isArray(test)) { + if (Array.isArray(test)) { return test.map(asRegExp).some(regExp => regExp.test(str)); } else { return test.test(str); @@ -145,11 +156,11 @@ ModuleFilenameHelpers.matchPart = (str, test) => { }; ModuleFilenameHelpers.matchObject = (obj, str) => { - if(obj.test) - if(!ModuleFilenameHelpers.matchPart(str, obj.test)) return false; - if(obj.include) - if(!ModuleFilenameHelpers.matchPart(str, obj.include)) return false; - if(obj.exclude) - if(ModuleFilenameHelpers.matchPart(str, obj.exclude)) return false; + if (obj.test) + if (!ModuleFilenameHelpers.matchPart(str, obj.test)) return false; + if (obj.include) + if (!ModuleFilenameHelpers.matchPart(str, obj.include)) return false; + if (obj.exclude) + if (ModuleFilenameHelpers.matchPart(str, obj.exclude)) return false; return true; }; diff --git a/lib/ModuleParseError.js b/lib/ModuleParseError.js index b76641f63..c8c6429ed 100644 --- a/lib/ModuleParseError.js +++ b/lib/ModuleParseError.js @@ -12,14 +12,24 @@ class ModuleParseError extends WebpackError { this.name = "ModuleParseError"; this.message = "Module parse failed: " + err.message; - this.message += "\nYou may need an appropriate loader to handle this file type."; - if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") { + this.message += + "\nYou may need an appropriate loader to handle this file type."; + if ( + err.loc && + typeof err.loc === "object" && + typeof err.loc.line === "number" + ) { var lineNumber = err.loc.line; - if(/[\0\u0001\u0002\u0003\u0004\u0005\u0006\u0007]/.test(source)) { // binary file + if (/[\0\u0001\u0002\u0003\u0004\u0005\u0006\u0007]/.test(source)) { + // binary file this.message += "\n(Source code omitted for this binary file)"; } else { source = source.split("\n"); - this.message += "\n| " + source.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| "); + this.message += + "\n| " + + source + .slice(Math.max(0, lineNumber - 3), lineNumber + 2) + .join("\n| "); } } else { this.message += "\n" + err.stack; diff --git a/lib/ModuleReason.js b/lib/ModuleReason.js index 06c1bcd9d..239584b6c 100644 --- a/lib/ModuleReason.js +++ b/lib/ModuleReason.js @@ -13,27 +13,24 @@ class ModuleReason { } hasChunk(chunk) { - if(this._chunks) { - if(this._chunks.has(chunk)) - return true; - } else if(this.module && this.module._chunks.has(chunk)) - return true; + if (this._chunks) { + if (this._chunks.has(chunk)) return true; + } else if (this.module && this.module._chunks.has(chunk)) return true; return false; } rewriteChunks(oldChunk, newChunks) { - if(!this._chunks) { - if(this.module) { - if(!this.module._chunks.has(oldChunk)) - return; + if (!this._chunks) { + if (this.module) { + if (!this.module._chunks.has(oldChunk)) return; this._chunks = new Set(this.module._chunks); } else { this._chunks = new Set(); } } - if(this._chunks.has(oldChunk)) { + if (this._chunks.has(oldChunk)) { this._chunks.delete(oldChunk); - for(let i = 0; i < newChunks.length; i++) { + for (let i = 0; i < newChunks.length; i++) { this._chunks.add(newChunks[i]); } } diff --git a/lib/ModuleTemplate.js b/lib/ModuleTemplate.js index 1a9191a3b..7dcc17630 100644 --- a/lib/ModuleTemplate.js +++ b/lib/ModuleTemplate.js @@ -13,20 +13,63 @@ module.exports = class ModuleTemplate extends Tapable { super(); this.runtimeTemplate = runtimeTemplate; this.hooks = { - content: new SyncWaterfallHook(["source", "module", "options", "dependencyTemplates"]), - module: new SyncWaterfallHook(["source", "module", "options", "dependencyTemplates"]), - render: new SyncWaterfallHook(["source", "module", "options", "dependencyTemplates"]), - package: new SyncWaterfallHook(["source", "module", "options", "dependencyTemplates"]), + content: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + module: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + render: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + package: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), hash: new SyncHook(["hash"]) }; } render(module, dependencyTemplates, options) { - const moduleSource = module.source(dependencyTemplates, this.runtimeTemplate); - const moduleSourcePostContent = this.hooks.content.call(moduleSource, module, options, dependencyTemplates); - const moduleSourcePostModule = this.hooks.module.call(moduleSourcePostContent, module, options, dependencyTemplates); - const moduleSourcePostRender = this.hooks.render.call(moduleSourcePostModule, module, options, dependencyTemplates); - return this.hooks.package.call(moduleSourcePostRender, module, options, dependencyTemplates); + const moduleSource = module.source( + dependencyTemplates, + this.runtimeTemplate + ); + const moduleSourcePostContent = this.hooks.content.call( + moduleSource, + module, + options, + dependencyTemplates + ); + const moduleSourcePostModule = this.hooks.module.call( + moduleSourcePostContent, + module, + options, + dependencyTemplates + ); + const moduleSourcePostRender = this.hooks.render.call( + moduleSourcePostModule, + module, + options, + dependencyTemplates + ); + return this.hooks.package.call( + moduleSourcePostRender, + module, + options, + dependencyTemplates + ); } updateHash(hash) { diff --git a/lib/ModuleWarning.js b/lib/ModuleWarning.js index 79180cd90..360bf9b4b 100644 --- a/lib/ModuleWarning.js +++ b/lib/ModuleWarning.js @@ -13,9 +13,15 @@ class ModuleWarning extends WebpackError { this.name = "ModuleWarning"; this.module = module; - this.message = warning && typeof warning === "object" && warning.message ? warning.message : warning; + this.message = + warning && typeof warning === "object" && warning.message + ? warning.message + : warning; this.warning = warning; - this.details = warning && typeof warning === "object" && warning.stack ? cleanUp(warning.stack, this.message) : undefined; + this.details = + warning && typeof warning === "object" && warning.stack + ? cleanUp(warning.stack, this.message) + : undefined; Error.captureStackTrace(this, this.constructor); } diff --git a/lib/MultiCompiler.js b/lib/MultiCompiler.js index 84165f904..1efdc6d85 100644 --- a/lib/MultiCompiler.js +++ b/lib/MultiCompiler.js @@ -21,8 +21,8 @@ module.exports = class MultiCompiler extends Tapable { watchClose: new SyncHook([]), watchRun: new MultiHook(compilers.map(c => c.hooks.watchRun)) }; - if(!Array.isArray(compilers)) { - compilers = Object.keys(compilers).map((name) => { + if (!Array.isArray(compilers)) { + compilers = Object.keys(compilers).map(name => { compilers[name].name = name; return compilers[name]; }); @@ -31,21 +31,23 @@ module.exports = class MultiCompiler extends Tapable { let doneCompilers = 0; let compilerStats = []; let index = 0; - for(const compiler of this.compilers) { + for (const compiler of this.compilers) { let compilerDone = false; const compilerIndex = index++; - compiler.hooks.done.tap("MultiCompiler", stats => { // eslint-disable-line no-loop-func - if(!compilerDone) { + compiler.hooks.done.tap("MultiCompiler", stats => { + // eslint-disable-line no-loop-func + if (!compilerDone) { compilerDone = true; doneCompilers++; } compilerStats[compilerIndex] = stats; - if(doneCompilers === this.compilers.length) { + if (doneCompilers === this.compilers.length) { this.hooks.done.call(new MultiStats(compilerStats)); } }); - compiler.hooks.invalid.tap("MultiCompiler", () => { // eslint-disable-line no-loop-func - if(compilerDone) { + compiler.hooks.invalid.tap("MultiCompiler", () => { + // eslint-disable-line no-loop-func + if (compilerDone) { compilerDone = false; doneCompilers--; } @@ -55,13 +57,16 @@ module.exports = class MultiCompiler extends Tapable { get outputPath() { let commonPath = this.compilers[0].outputPath; - for(const compiler of this.compilers) { - while(compiler.outputPath.indexOf(commonPath) !== 0 && /[/\\]/.test(commonPath)) { + for (const compiler of this.compilers) { + while ( + compiler.outputPath.indexOf(commonPath) !== 0 && + /[/\\]/.test(commonPath) + ) { commonPath = commonPath.replace(/[/\\][^/\\]*$/, ""); } } - if(!commonPath && this.compilers[0].outputPath[0] === "/") return "/"; + if (!commonPath && this.compilers[0].outputPath[0] === "/") return "/"; return commonPath; } @@ -74,13 +79,13 @@ module.exports = class MultiCompiler extends Tapable { } set inputFileSystem(value) { - for(const compiler of this.compilers) { + for (const compiler of this.compilers) { compiler.inputFileSystem = value; } } set outputFileSystem(value) { - for(const compiler of this.compilers) { + for (const compiler of this.compilers) { compiler.outputFileSystem = value; } } @@ -88,23 +93,25 @@ module.exports = class MultiCompiler extends Tapable { validateDependencies(callback) { const edges = new Set(); const missing = []; - const targetFound = (compiler) => { - for(const edge of edges) { - if(edge.target === compiler) { + const targetFound = compiler => { + for (const edge of edges) { + if (edge.target === compiler) { return true; } } return false; }; const sortEdges = (e1, e2) => { - return e1.source.name.localeCompare(e2.source.name) || - e1.target.name.localeCompare(e2.target.name); + return ( + e1.source.name.localeCompare(e2.source.name) || + e1.target.name.localeCompare(e2.target.name) + ); }; - for(const source of this.compilers) { - if(source.dependencies) { - for(const dep of source.dependencies) { - const target = this.compilers.find((c) => c.name === dep); - if(!target) { + for (const source of this.compilers) { + if (source.dependencies) { + for (const dep of source.dependencies) { + const target = this.compilers.find(c => c.name === dep); + if (!target) { missing.push(dep); } else { edges.add({ @@ -115,26 +122,28 @@ module.exports = class MultiCompiler extends Tapable { } } } - const errors = missing.map((m) => `Compiler dependency \`${m}\` not found.`); - const stack = this.compilers.filter((c) => !targetFound(c)); - while(stack.length > 0) { + const errors = missing.map(m => `Compiler dependency \`${m}\` not found.`); + const stack = this.compilers.filter(c => !targetFound(c)); + while (stack.length > 0) { const current = stack.pop(); - for(const edge of edges) { - if(edge.source === current) { + for (const edge of edges) { + if (edge.source === current) { edges.delete(edge); const target = edge.target; - if(!targetFound(target)) { + if (!targetFound(target)) { stack.push(target); } } } } - if(edges.size > 0) { - const lines = Array.from(edges).sort(sortEdges).map(edge => `${edge.source.name} -> ${edge.target.name}`); + if (edges.size > 0) { + const lines = Array.from(edges) + .sort(sortEdges) + .map(edge => `${edge.source.name} -> ${edge.target.name}`); lines.unshift("Circular dependency found in compiler dependencies."); errors.unshift(lines.join("\n")); } - if(errors.length > 0) { + if (errors.length > 0) { const message = errors.join("\n"); callback(new Error(message)); return false; @@ -145,29 +154,32 @@ module.exports = class MultiCompiler extends Tapable { runWithDependencies(compilers, fn, callback) { const fulfilledNames = new Set(); let remainingCompilers = compilers; - const isDependencyFulfilled = (d) => fulfilledNames.has(d); + const isDependencyFulfilled = d => fulfilledNames.has(d); const getReadyCompilers = () => { let readyCompilers = []; let list = remainingCompilers; remainingCompilers = []; - for(const c of list) { - const ready = !c.dependencies || c.dependencies.every(isDependencyFulfilled); - if(ready) - readyCompilers.push(c); - else - remainingCompilers.push(c); + for (const c of list) { + const ready = + !c.dependencies || c.dependencies.every(isDependencyFulfilled); + if (ready) readyCompilers.push(c); + else remainingCompilers.push(c); } return readyCompilers; }; - const runCompilers = (callback) => { - if(remainingCompilers.length === 0) return callback(); - asyncLib.map(getReadyCompilers(), (compiler, callback) => { - fn(compiler, (err) => { - if(err) return callback(err); - fulfilledNames.add(compiler.name); - runCompilers(callback); - }); - }, callback); + const runCompilers = callback => { + if (remainingCompilers.length === 0) return callback(); + asyncLib.map( + getReadyCompilers(), + (compiler, callback) => { + fn(compiler, err => { + if (err) return callback(err); + fulfilledNames.add(compiler.name); + runCompilers(callback); + }); + }, + callback + ); }; runCompilers(callback); } @@ -176,34 +188,42 @@ module.exports = class MultiCompiler extends Tapable { let watchings = []; let allStats = this.compilers.map(() => null); let compilerStatus = this.compilers.map(() => false); - if(this.validateDependencies(handler)) { - this.runWithDependencies(this.compilers, (compiler, callback) => { - const compilerIdx = this.compilers.indexOf(compiler); - let firstRun = true; - let watching = compiler.watch(Array.isArray(watchOptions) ? watchOptions[compilerIdx] : watchOptions, (err, stats) => { - if(err) - handler(err); - if(stats) { - allStats[compilerIdx] = stats; - compilerStatus[compilerIdx] = "new"; - if(compilerStatus.every(Boolean)) { - const freshStats = allStats.filter((s, idx) => { - return compilerStatus[idx] === "new"; - }); - compilerStatus.fill(true); - const multiStats = new MultiStats(freshStats); - handler(null, multiStats); + if (this.validateDependencies(handler)) { + this.runWithDependencies( + this.compilers, + (compiler, callback) => { + const compilerIdx = this.compilers.indexOf(compiler); + let firstRun = true; + let watching = compiler.watch( + Array.isArray(watchOptions) + ? watchOptions[compilerIdx] + : watchOptions, + (err, stats) => { + if (err) handler(err); + if (stats) { + allStats[compilerIdx] = stats; + compilerStatus[compilerIdx] = "new"; + if (compilerStatus.every(Boolean)) { + const freshStats = allStats.filter((s, idx) => { + return compilerStatus[idx] === "new"; + }); + compilerStatus.fill(true); + const multiStats = new MultiStats(freshStats); + handler(null, multiStats); + } + } + if (firstRun && !err) { + firstRun = false; + callback(); + } } - } - if(firstRun && !err) { - firstRun = false; - callback(); - } - }); - watchings.push(watching); - }, () => { - // ignore - }); + ); + watchings.push(watching); + }, + () => { + // ignore + } + ); } return new MultiWatching(watchings, this); @@ -211,24 +231,28 @@ module.exports = class MultiCompiler extends Tapable { run(callback) { const allStats = this.compilers.map(() => null); - if(this.validateDependencies(callback)) { - this.runWithDependencies(this.compilers, ((compiler, callback) => { - const compilerIdx = this.compilers.indexOf(compiler); - compiler.run((err, stats) => { - if(err) return callback(err); - allStats[compilerIdx] = stats; - callback(); - }); - }), (err) => { - if(err) return callback(err); - callback(null, new MultiStats(allStats)); - }); + if (this.validateDependencies(callback)) { + this.runWithDependencies( + this.compilers, + (compiler, callback) => { + const compilerIdx = this.compilers.indexOf(compiler); + compiler.run((err, stats) => { + if (err) return callback(err); + allStats[compilerIdx] = stats; + callback(); + }); + }, + err => { + if (err) return callback(err); + callback(null, new MultiStats(allStats)); + } + ); } } purgeInputFileSystem() { - for(const compiler of this.compilers) { - if(compiler.inputFileSystem && compiler.inputFileSystem.purge) + for (const compiler of this.compilers) { + if (compiler.inputFileSystem && compiler.inputFileSystem.purge) compiler.inputFileSystem.purge(); } } diff --git a/lib/MultiEntryPlugin.js b/lib/MultiEntryPlugin.js index fb0743466..29e806429 100644 --- a/lib/MultiEntryPlugin.js +++ b/lib/MultiEntryPlugin.js @@ -16,34 +16,43 @@ module.exports = class MultiEntryPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("MultiEntryPlugin", (compilation, { - normalModuleFactory - }) => { - const multiModuleFactory = new MultiModuleFactory(); + compiler.hooks.compilation.tap( + "MultiEntryPlugin", + (compilation, { normalModuleFactory }) => { + const multiModuleFactory = new MultiModuleFactory(); - compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory); - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); + compilation.dependencyFactories.set( + MultiEntryDependency, + multiModuleFactory + ); + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); - compiler.hooks.make.tapAsync("MultiEntryPlugin", (compilation, callback) => { - const { - context, - entries, - name - } = this; + compiler.hooks.make.tapAsync( + "MultiEntryPlugin", + (compilation, callback) => { + const { context, entries, name } = this; - const dep = MultiEntryPlugin.createDependency(entries, name); - compilation.addEntry(context, dep, name, callback); - }); + const dep = MultiEntryPlugin.createDependency(entries, name); + compilation.addEntry(context, dep, name, callback); + } + ); } static createDependency(entries, name) { - return new MultiEntryDependency(entries.map((e, idx) => { - const dep = new SingleEntryDependency(e); - // Because entrypoints are not dependencies found in an - // existing module, we give it a synthetic id - dep.loc = `${name}:${100000 + idx}`; - return dep; - }), name); + return new MultiEntryDependency( + entries.map((e, idx) => { + const dep = new SingleEntryDependency(e); + // Because entrypoints are not dependencies found in an + // existing module, we give it a synthetic id + dep.loc = `${name}:${100000 + idx}`; + return dep; + }), + name + ); } }; diff --git a/lib/MultiModule.js b/lib/MultiModule.js index 1c983fe88..19aa25cb6 100644 --- a/lib/MultiModule.js +++ b/lib/MultiModule.js @@ -9,7 +9,6 @@ const Template = require("./Template"); const RawSource = require("webpack-sources").RawSource; class MultiModule extends Module { - constructor(context, dependencies, name) { super("javascript/dynamic", context); @@ -19,11 +18,13 @@ class MultiModule extends Module { } identifier() { - return `multi ${this.dependencies.map((d) => d.request).join(" ")}`; + return `multi ${this.dependencies.map(d => d.request).join(" ")}`; } readableIdentifier(requestShortener) { - return `multi ${this.dependencies.map((d) => requestShortener.shorten(d.request)).join(" ")}`; + return `multi ${this.dependencies + .map(d => requestShortener.shorten(d.request)) + .join(" ")}`; } build(options, compilation, resolver, fs, callback) { @@ -50,17 +51,18 @@ class MultiModule extends Module { source(dependencyTemplates, runtimeTemplate) { const str = []; let idx = 0; - for(const dep of this.dependencies) { - if(dep.module) { - if(idx === this.dependencies.length - 1) - str.push("module.exports = "); + for (const dep of this.dependencies) { + if (dep.module) { + if (idx === this.dependencies.length - 1) str.push("module.exports = "); str.push("__webpack_require__("); - if(runtimeTemplate.outputOptions.pathinfo) + if (runtimeTemplate.outputOptions.pathinfo) str.push(Template.toComment(dep.request)); str.push(`${JSON.stringify(dep.module.id)}`); str.push(")"); } else { - const content = require("./dependencies/WebpackMissingModule").module(dep.request); + const content = require("./dependencies/WebpackMissingModule").module( + dep.request + ); str.push(content); } str.push(";\n"); diff --git a/lib/MultiModuleFactory.js b/lib/MultiModuleFactory.js index ee96de057..f0af1fdab 100644 --- a/lib/MultiModuleFactory.js +++ b/lib/MultiModuleFactory.js @@ -15,6 +15,9 @@ module.exports = class MultiModuleFactory extends Tapable { create(data, callback) { const dependency = data.dependencies[0]; - callback(null, new MultiModule(data.context, dependency.dependencies, dependency.name)); + callback( + null, + new MultiModule(data.context, dependency.dependencies, dependency.name) + ); } }; diff --git a/lib/MultiStats.js b/lib/MultiStats.js index cb20a3741..4713524b8 100644 --- a/lib/MultiStats.js +++ b/lib/MultiStats.js @@ -6,7 +6,8 @@ const Stats = require("./Stats"); -const optionOrFallback = (optionValue, fallbackValue) => optionValue !== undefined ? optionValue : fallbackValue; +const optionOrFallback = (optionValue, fallbackValue) => + optionValue !== undefined ? optionValue : fallbackValue; class MultiStats { constructor(stats) { @@ -15,17 +16,21 @@ class MultiStats { } hasErrors() { - return this.stats.map((stat) => stat.hasErrors()).reduce((a, b) => a || b, false); + return this.stats + .map(stat => stat.hasErrors()) + .reduce((a, b) => a || b, false); } hasWarnings() { - return this.stats.map((stat) => stat.hasWarnings()).reduce((a, b) => a || b, false); + return this.stats + .map(stat => stat.hasWarnings()) + .reduce((a, b) => a || b, false); } toJson(options, forToString) { - if(typeof options === "boolean" || typeof options === "string") { + if (typeof options === "boolean" || typeof options === "string") { options = Stats.presetToOptions(options); - } else if(!options) { + } else if (!options) { options = {}; } const jsons = this.stats.map((stat, idx) => { @@ -34,38 +39,45 @@ class MultiStats { obj.name = stat.compilation && stat.compilation.name; return obj; }); - const showVersion = typeof options.version === "undefined" ? jsons.every(j => j.version) : options.version !== false; - const showHash = typeof options.hash === "undefined" ? jsons.every(j => j.hash) : options.hash !== false; - if(showVersion) { - for(const j of jsons) { + const showVersion = + typeof options.version === "undefined" + ? jsons.every(j => j.version) + : options.version !== false; + const showHash = + typeof options.hash === "undefined" + ? jsons.every(j => j.hash) + : options.hash !== false; + if (showVersion) { + for (const j of jsons) { delete j.version; } } const obj = { errors: jsons.reduce((arr, j) => { - return arr.concat(j.errors.map(msg => { - return `(${j.name}) ${msg}`; - })); + return arr.concat( + j.errors.map(msg => { + return `(${j.name}) ${msg}`; + }) + ); }, []), warnings: jsons.reduce((arr, j) => { - return arr.concat(j.warnings.map(msg => { - return `(${j.name}) ${msg}`; - })); + return arr.concat( + j.warnings.map(msg => { + return `(${j.name}) ${msg}`; + }) + ); }, []) }; - if(showVersion) - obj.version = require("../package.json").version; - if(showHash) - obj.hash = this.hash; - if(options.children !== false) - obj.children = jsons; + if (showVersion) obj.version = require("../package.json").version; + if (showHash) obj.hash = this.hash; + if (options.children !== false) obj.children = jsons; return obj; } toString(options) { - if(typeof options === "boolean" || typeof options === "string") { + if (typeof options === "boolean" || typeof options === "string") { options = Stats.presetToOptions(options); - } else if(!options) { + } else if (!options) { options = {}; } diff --git a/lib/MultiWatching.js b/lib/MultiWatching.js index 0e586d936..80a6a4a53 100644 --- a/lib/MultiWatching.js +++ b/lib/MultiWatching.js @@ -13,20 +13,24 @@ class MultiWatching { } invalidate() { - for(const watching of this.watchings) { + for (const watching of this.watchings) { watching.invalidate(); } } close(callback) { - asyncLib.forEach(this.watchings, (watching, finishedCallback) => { - watching.close(finishedCallback); - }, err => { - this.compiler.hooks.watchClose.call(); - if(typeof callback === "function") { - callback(err); + asyncLib.forEach( + this.watchings, + (watching, finishedCallback) => { + watching.close(finishedCallback); + }, + err => { + this.compiler.hooks.watchClose.call(); + if (typeof callback === "function") { + callback(err); + } } - }); + ); } } diff --git a/lib/NamedChunksPlugin.js b/lib/NamedChunksPlugin.js index f011c2d12..0cb5b6bf3 100644 --- a/lib/NamedChunksPlugin.js +++ b/lib/NamedChunksPlugin.js @@ -5,7 +5,6 @@ "use strict"; class NamedChunksPlugin { - static defaultNameResolver(chunk) { return chunk.name || null; } @@ -15,10 +14,10 @@ class NamedChunksPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("NamedChunksPlugin", (compilation) => { - compilation.hooks.beforeChunkIds.tap("NamedChunksPlugin", (chunks) => { - for(const chunk of chunks) { - if(chunk.id === null) { + compiler.hooks.compilation.tap("NamedChunksPlugin", compilation => { + compilation.hooks.beforeChunkIds.tap("NamedChunksPlugin", chunks => { + for (const chunk of chunks) { + if (chunk.id === null) { chunk.id = this.nameResolver(chunk); } } diff --git a/lib/NamedModulesPlugin.js b/lib/NamedModulesPlugin.js index 4e8f6bb57..cfcfbab11 100644 --- a/lib/NamedModulesPlugin.js +++ b/lib/NamedModulesPlugin.js @@ -10,10 +10,10 @@ class NamedModulesPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("NamedModulesPlugin", (compilation) => { - compilation.hooks.beforeModuleIds.tap("NamedModulesPlugin", (modules) => { - for(const module of modules) { - if(module.id === null && module.libIdent) { + compiler.hooks.compilation.tap("NamedModulesPlugin", compilation => { + compilation.hooks.beforeModuleIds.tap("NamedModulesPlugin", modules => { + for (const module of modules) { + if (module.id === null && module.libIdent) { module.id = module.libIdent({ context: this.options.context || compiler.options.context }); diff --git a/lib/NoEmitOnErrorsPlugin.js b/lib/NoEmitOnErrorsPlugin.js index 679c3c577..2c37c4979 100644 --- a/lib/NoEmitOnErrorsPlugin.js +++ b/lib/NoEmitOnErrorsPlugin.js @@ -6,14 +6,12 @@ class NoEmitOnErrorsPlugin { apply(compiler) { - compiler.hooks.shouldEmit.tap("NoEmitOnErrorsPlugin", (compilation) => { - if(compilation.getStats().hasErrors()) - return false; + compiler.hooks.shouldEmit.tap("NoEmitOnErrorsPlugin", compilation => { + if (compilation.getStats().hasErrors()) return false; }); - compiler.hooks.compilation.tap("NoEmitOnErrorsPlugin", (compilation) => { + compiler.hooks.compilation.tap("NoEmitOnErrorsPlugin", compilation => { compilation.hooks.shouldRecord.tap("NoEmitOnErrorsPlugin", () => { - if(compilation.getStats().hasErrors()) - return false; + if (compilation.getStats().hasErrors()) return false; }); }); } diff --git a/lib/NoModeWarning.js b/lib/NoModeWarning.js index d0ae98f50..f42f0e156 100644 --- a/lib/NoModeWarning.js +++ b/lib/NoModeWarning.js @@ -11,7 +11,8 @@ module.exports = class NoModeWarning extends WebpackError { super(); this.name = "NoModeWarning"; - this.message = "configuration\n" + + this.message = + "configuration\n" + "The 'mode' option has not been set. " + "Set 'mode' option to 'development' or 'production' to enable defaults for this environment. "; diff --git a/lib/NodeStuffPlugin.js b/lib/NodeStuffPlugin.js index 6a87557ee..515d4b173 100644 --- a/lib/NodeStuffPlugin.js +++ b/lib/NodeStuffPlugin.js @@ -17,88 +17,162 @@ class NodeStuffPlugin { apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("NodeStuffPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); + compiler.hooks.compilation.tap( + "NodeStuffPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(parserOptions.node === false) - return; + const handler = (parser, parserOptions) => { + if (parserOptions.node === false) return; - let localOptions = options; - if(parserOptions.node) - localOptions = Object.assign({}, localOptions, parserOptions.node); + let localOptions = options; + if (parserOptions.node) + localOptions = Object.assign({}, localOptions, parserOptions.node); - const setConstant = (expressionName, value) => { - parser.hooks.expression.for(expressionName).tap("NodeStuffPlugin", () => { - parser.state.current.addVariable(expressionName, JSON.stringify(value)); - return true; - }); - }; + const setConstant = (expressionName, value) => { + parser.hooks.expression + .for(expressionName) + .tap("NodeStuffPlugin", () => { + parser.state.current.addVariable( + expressionName, + JSON.stringify(value) + ); + return true; + }); + }; - const setModuleConstant = (expressionName, fn) => { - parser.hooks.expression.for(expressionName).tap("NodeStuffPlugin", () => { - parser.state.current.addVariable(expressionName, JSON.stringify(fn(parser.state.module))); - return true; - }); - }; - const context = compiler.context; - if(localOptions.__filename === "mock") { - setConstant("__filename", "/index.js"); - } else if(localOptions.__filename) { - setModuleConstant("__filename", module => path.relative(context, module.resource)); - } - parser.hooks.evaluateIdentifier.for("__filename").tap("NodeStuffPlugin", expr => { - if(!parser.state.module) return; - const resource = parser.state.module.resource; - const i = resource.indexOf("?"); - return ParserHelpers.evaluateToString(i < 0 ? resource : resource.substr(0, i))(expr); - }); - if(localOptions.__dirname === "mock") { - setConstant("__dirname", "/"); - } else if(localOptions.__dirname) { - setModuleConstant("__dirname", module => path.relative(context, module.context)); - } - parser.hooks.evaluateIdentifier.for("__dirname").tap("NodeStuffPlugin", expr => { - if(!parser.state.module) return; - return ParserHelpers.evaluateToString(parser.state.module.context)(expr); - }); - parser.hooks.expression.for("require.main").tap("NodeStuffPlugin", ParserHelpers.toConstantDependencyWithWebpackRequire(parser, "__webpack_require__.c[__webpack_require__.s]")); - parser.hooks.expression.for("require.extensions").tap("NodeStuffPlugin", ParserHelpers.expressionIsUnsupported(parser, "require.extensions is not supported by webpack. Use a loader instead.")); - parser.hooks.expression.for("module.loaded").tap("NodeStuffPlugin", expr => { - parser.state.module.buildMeta.moduleConcatenationBailout = "module.loaded"; - return ParserHelpers.toConstantDependency(parser, "module.l")(expr); - }); - parser.hooks.expression.for("module.id").tap("NodeStuffPlugin", expr => { - parser.state.module.buildMeta.moduleConcatenationBailout = "module.id"; - return ParserHelpers.toConstantDependency(parser, "module.i")(expr); - }); - parser.hooks.expression.for("module.exports").tap("NodeStuffPlugin", () => { - const module = parser.state.module; - const isHarmony = module.buildMeta && module.buildMeta.exportsType; - if(!isHarmony) - return true; - }); - parser.hooks.evaluateIdentifier.for("module.hot").tap("NodeStuffPlugin", ParserHelpers.evaluateToIdentifier("module.hot", false)); - parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => { - const module = parser.state.module; - const isHarmony = module.buildMeta && module.buildMeta.exportsType; - let moduleJsPath = path.join(__dirname, "..", "buildin", isHarmony ? "harmony-module.js" : "module.js"); - if(module.context) { - moduleJsPath = path.relative(parser.state.module.context, moduleJsPath); - if(!/^[A-Z]:/i.test(moduleJsPath)) { - moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`; - } + const setModuleConstant = (expressionName, fn) => { + parser.hooks.expression + .for(expressionName) + .tap("NodeStuffPlugin", () => { + parser.state.current.addVariable( + expressionName, + JSON.stringify(fn(parser.state.module)) + ); + return true; + }); + }; + const context = compiler.context; + if (localOptions.__filename === "mock") { + setConstant("__filename", "/index.js"); + } else if (localOptions.__filename) { + setModuleConstant("__filename", module => + path.relative(context, module.resource) + ); } - return ParserHelpers.addParsedVariableToModule(parser, "module", `require(${JSON.stringify(moduleJsPath)})(module)`); - }); - }; + parser.hooks.evaluateIdentifier + .for("__filename") + .tap("NodeStuffPlugin", expr => { + if (!parser.state.module) return; + const resource = parser.state.module.resource; + const i = resource.indexOf("?"); + return ParserHelpers.evaluateToString( + i < 0 ? resource : resource.substr(0, i) + )(expr); + }); + if (localOptions.__dirname === "mock") { + setConstant("__dirname", "/"); + } else if (localOptions.__dirname) { + setModuleConstant("__dirname", module => + path.relative(context, module.context) + ); + } + parser.hooks.evaluateIdentifier + .for("__dirname") + .tap("NodeStuffPlugin", expr => { + if (!parser.state.module) return; + return ParserHelpers.evaluateToString( + parser.state.module.context + )(expr); + }); + parser.hooks.expression + .for("require.main") + .tap( + "NodeStuffPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.c[__webpack_require__.s]" + ) + ); + parser.hooks.expression + .for("require.extensions") + .tap( + "NodeStuffPlugin", + ParserHelpers.expressionIsUnsupported( + parser, + "require.extensions is not supported by webpack. Use a loader instead." + ) + ); + parser.hooks.expression + .for("module.loaded") + .tap("NodeStuffPlugin", expr => { + parser.state.module.buildMeta.moduleConcatenationBailout = + "module.loaded"; + return ParserHelpers.toConstantDependency(parser, "module.l")( + expr + ); + }); + parser.hooks.expression + .for("module.id") + .tap("NodeStuffPlugin", expr => { + parser.state.module.buildMeta.moduleConcatenationBailout = + "module.id"; + return ParserHelpers.toConstantDependency(parser, "module.i")( + expr + ); + }); + parser.hooks.expression + .for("module.exports") + .tap("NodeStuffPlugin", () => { + const module = parser.state.module; + const isHarmony = + module.buildMeta && module.buildMeta.exportsType; + if (!isHarmony) return true; + }); + parser.hooks.evaluateIdentifier + .for("module.hot") + .tap( + "NodeStuffPlugin", + ParserHelpers.evaluateToIdentifier("module.hot", false) + ); + parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => { + const module = parser.state.module; + const isHarmony = module.buildMeta && module.buildMeta.exportsType; + let moduleJsPath = path.join( + __dirname, + "..", + "buildin", + isHarmony ? "harmony-module.js" : "module.js" + ); + if (module.context) { + moduleJsPath = path.relative( + parser.state.module.context, + moduleJsPath + ); + if (!/^[A-Z]:/i.test(moduleJsPath)) { + moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`; + } + } + return ParserHelpers.addParsedVariableToModule( + parser, + "module", + `require(${JSON.stringify(moduleJsPath)})(module)` + ); + }); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("NodeStuffPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("NodeStuffPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("NodeStuffPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("NodeStuffPlugin", handler); + } + ); } } module.exports = NodeStuffPlugin; diff --git a/lib/NormalModule.js b/lib/NormalModule.js index 32c8acee0..849aaabac 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -11,7 +11,8 @@ const SourceMapSource = require("webpack-sources").SourceMapSource; const OriginalSource = require("webpack-sources").OriginalSource; const RawSource = require("webpack-sources").RawSource; const CachedSource = require("webpack-sources").CachedSource; -const LineToLineMappedSource = require("webpack-sources").LineToLineMappedSource; +const LineToLineMappedSource = require("webpack-sources") + .LineToLineMappedSource; const WebpackError = require("./WebpackError"); const Module = require("./Module"); @@ -23,30 +24,31 @@ const ModuleWarning = require("./ModuleWarning"); const runLoaders = require("loader-runner").runLoaders; const getContext = require("loader-runner").getContext; -const asString = (buf) => { - if(Buffer.isBuffer(buf)) { +const asString = buf => { + if (Buffer.isBuffer(buf)) { return buf.toString("utf-8"); } return buf; }; const asBuffer = str => { - if(!Buffer.isBuffer(str)) { + if (!Buffer.isBuffer(str)) { return Buffer.from(str, "utf-8"); } return str; }; const contextify = (context, request) => { - return request.split("!").map(r => { - const splitPath = r.split("?"); - splitPath[0] = path.relative(context, splitPath[0]); - if(path.sep === "\\") - splitPath[0] = splitPath[0].replace(/\\/g, "/"); - if(splitPath[0].indexOf("../") !== 0) - splitPath[0] = "./" + splitPath[0]; - return splitPath.join("?"); - }).join("!"); + return request + .split("!") + .map(r => { + const splitPath = r.split("?"); + splitPath[0] = path.relative(context, splitPath[0]); + if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/"); + if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0]; + return splitPath.join("?"); + }) + .join("!"); }; class NonErrorEmittedError extends WebpackError { @@ -63,7 +65,6 @@ class NonErrorEmittedError extends WebpackError { const dependencyTemplatesHashMap = new WeakMap(); class NormalModule extends Module { - constructor({ type, request, @@ -86,8 +87,7 @@ class NormalModule extends Module { this.generator = generator; this.resource = resource; this.loaders = loaders; - if(resolveOptions !== undefined) - this.resolveOptions = resolveOptions; + if (resolveOptions !== undefined) this.resolveOptions = resolveOptions; // Info from Build this.error = null; @@ -119,16 +119,16 @@ class NormalModule extends Module { nameForCondition() { const idx = this.resource.indexOf("?"); - if(idx >= 0) return this.resource.substr(0, idx); + if (idx >= 0) return this.resource.substr(0, idx); return this.resource; } createSourceForAsset(name, content, sourceMap) { - if(!sourceMap) { + if (!sourceMap) { return new RawSource(content); } - if(typeof sourceMap === "string") { + if (typeof sourceMap === "string") { return new OriginalSource(content, sourceMap); } @@ -138,14 +138,13 @@ class NormalModule extends Module { createLoaderContext(resolver, options, compilation, fs) { const loaderContext = { version: 2, - emitWarning: (warning) => { - if(!(warning instanceof Error)) + emitWarning: warning => { + if (!(warning instanceof Error)) warning = new NonErrorEmittedError(warning); this.warnings.push(new ModuleWarning(this, warning)); }, - emitError: (error) => { - if(!(error instanceof Error)) - error = new NonErrorEmittedError(error); + emitError: error => { + if (!(error instanceof Error)) error = new NonErrorEmittedError(error); this.errors.push(new ModuleError(this, error)); }, exec: (code, filename) => { @@ -159,8 +158,12 @@ class NormalModule extends Module { resolver.resolve({}, context, request, {}, callback); }, emitFile: (name, content, sourceMap) => { - if(!this.buildInfo.assets) this.buildInfo.assets = Object.create(null); - this.buildInfo.assets[name] = this.createSourceForAsset(name, content, sourceMap); + if (!this.buildInfo.assets) this.buildInfo.assets = Object.create(null); + this.buildInfo.assets[name] = this.createSourceForAsset( + name, + content, + sourceMap + ); }, rootContext: options.context, webpack: true, @@ -168,35 +171,37 @@ class NormalModule extends Module { _module: this, _compilation: compilation, _compiler: compilation.compiler, - fs: fs, + fs: fs }; compilation.hooks.normalModuleLoader.call(loaderContext, this); - if(options.loader) - Object.assign(loaderContext, options.loader); + if (options.loader) Object.assign(loaderContext, options.loader); return loaderContext; } createSource(source, resourceBuffer, sourceMap) { // if there is no identifier return raw source - if(!this.identifier) { + if (!this.identifier) { return new RawSource(source); } // from here on we assume we have an identifier const identifier = this.identifier(); - if(this.lineToLine && resourceBuffer) { + if (this.lineToLine && resourceBuffer) { return new LineToLineMappedSource( - source, identifier, asString(resourceBuffer)); + source, + identifier, + asString(resourceBuffer) + ); } - if(this.useSourceMap && sourceMap) { + if (this.useSourceMap && sourceMap) { return new SourceMapSource(source, identifier, sourceMap); } - if(Buffer.isBuffer(source)) { + if (Buffer.isBuffer(source)) { return new RawSource(source); } @@ -204,39 +209,61 @@ class NormalModule extends Module { } doBuild(options, compilation, resolver, fs, callback) { - const loaderContext = this.createLoaderContext(resolver, options, compilation, fs); + const loaderContext = this.createLoaderContext( + resolver, + options, + compilation, + fs + ); - runLoaders({ - resource: this.resource, - loaders: this.loaders, - context: loaderContext, - readResource: fs.readFile.bind(fs) - }, (err, result) => { - if(result) { - this.buildInfo.cacheable = result.cacheable; - this.buildInfo.fileDependencies = new Set(result.fileDependencies); - this.buildInfo.contextDependencies = new Set(result.contextDependencies); + runLoaders( + { + resource: this.resource, + loaders: this.loaders, + context: loaderContext, + readResource: fs.readFile.bind(fs) + }, + (err, result) => { + if (result) { + this.buildInfo.cacheable = result.cacheable; + this.buildInfo.fileDependencies = new Set(result.fileDependencies); + this.buildInfo.contextDependencies = new Set( + result.contextDependencies + ); + } + + if (err) { + const error = new ModuleBuildError(this, err); + return callback(error); + } + + const resourceBuffer = result.resourceBuffer; + const source = result.result[0]; + const sourceMap = result.result.length >= 1 ? result.result[1] : null; + const extraInfo = result.result.length >= 2 ? result.result[2] : null; + + if (!Buffer.isBuffer(source) && typeof source !== "string") { + const error = new ModuleBuildError( + this, + new Error("Final loader didn't return a Buffer or String") + ); + return callback(error); + } + + this._source = this.createSource( + this.binary ? asBuffer(source) : asString(source), + resourceBuffer, + sourceMap + ); + this._ast = + typeof extraInfo === "object" && + extraInfo !== null && + extraInfo.webpackAST !== undefined + ? extraInfo.webpackAST + : null; + return callback(); } - - if(err) { - const error = new ModuleBuildError(this, err); - return callback(error); - } - - const resourceBuffer = result.resourceBuffer; - const source = result.result[0]; - const sourceMap = result.result.length >= 1 ? result.result[1] : null; - const extraInfo = result.result.length >= 2 ? result.result[2] : null; - - if(!Buffer.isBuffer(source) && typeof source !== "string") { - const error = new ModuleBuildError(this, new Error("Final loader didn't return a Buffer or String")); - return callback(error); - } - - this._source = this.createSource(this.binary ? asBuffer(source) : asString(source), resourceBuffer, sourceMap); - this._ast = typeof extraInfo === "object" && extraInfo !== null && extraInfo.webpackAST !== undefined ? extraInfo.webpackAST : null; - return callback(); - }); + ); } markModuleAsErrored(error) { @@ -245,17 +272,19 @@ class NormalModule extends Module { this.error = error; this.errors.push(this.error); - this._source = new RawSource("throw new Error(" + JSON.stringify(this.error.message) + ");"); + this._source = new RawSource( + "throw new Error(" + JSON.stringify(this.error.message) + ");" + ); this._ast = null; } applyNoParseRule(rule, content) { // must start with "rule" if rule is a string - if(typeof rule === "string") { + if (typeof rule === "string") { return content.indexOf(rule) === 0; } - if(typeof rule === "function") { + if (typeof rule === "function") { return rule(content); } // we assume rule is a regexp @@ -268,21 +297,21 @@ class NormalModule extends Module { shouldPreventParsing(noParseRule, request) { // if no noParseRule exists, return false // the module !must! be parsed. - if(!noParseRule) { + if (!noParseRule) { return false; } // we only have one rule to check - if(!Array.isArray(noParseRule)) { + if (!Array.isArray(noParseRule)) { // returns "true" if the module is !not! to be parsed return this.applyNoParseRule(noParseRule, request); } - for(let i = 0; i < noParseRule.length; i++) { + for (let i = 0; i < noParseRule.length; i++) { const rule = noParseRule[i]; // early exit on first truthy match // this module is !not! to be parsed - if(this.applyNoParseRule(rule, request)) { + if (this.applyNoParseRule(rule, request)) { return true; } } @@ -302,15 +331,15 @@ class NormalModule extends Module { this.buildInfo = { cacheable: false, fileDependencies: new Set(), - contextDependencies: new Set(), + contextDependencies: new Set() }; - return this.doBuild(options, compilation, resolver, fs, (err) => { + return this.doBuild(options, compilation, resolver, fs, err => { this._cachedSource = undefined; this._cachedSourceHash = undefined; // if we have an error mark module as failed and exit - if(err) { + if (err) { this.markModuleAsErrored(err); return callback(); } @@ -318,7 +347,7 @@ class NormalModule extends Module { // check if this module should !not! be parsed. // if so, exit here; const noParseRule = options.module && options.module.noParse; - if(this.shouldPreventParsing(noParseRule, this.request)) { + if (this.shouldPreventParsing(noParseRule, this.request)) { return callback(); } @@ -335,23 +364,27 @@ class NormalModule extends Module { }; try { - const result = this.parser.parse(this._ast || this._source.source(), { - current: this, - module: this, - compilation: compilation, - options: options - }, (err, result) => { - if(err) { - handleParseError(err); - } else { - handleParseResult(result); + const result = this.parser.parse( + this._ast || this._source.source(), + { + current: this, + module: this, + compilation: compilation, + options: options + }, + (err, result) => { + if (err) { + handleParseError(err); + } else { + handleParseResult(result); + } } - }); - if(result !== undefined) { + ); + if (result !== undefined) { // parse is sync handleParseResult(result); } - } catch(e) { + } catch (e) { handleParseError(e); } }); @@ -364,12 +397,16 @@ class NormalModule extends Module { source(dependencyTemplates, runtimeTemplate) { const hashDigest = this.getHashDigest(dependencyTemplates); - if(this._cachedSourceHash === hashDigest) { + if (this._cachedSourceHash === hashDigest) { // We can reuse the cached source return this._cachedSource; } - const source = this.generator.generate(this, dependencyTemplates, runtimeTemplate); + const source = this.generator.generate( + this, + dependencyTemplates, + runtimeTemplate + ); const cachedSource = new CachedSource(source); this._cachedSource = cachedSource; @@ -383,23 +420,23 @@ class NormalModule extends Module { needRebuild(fileTimestamps, contextTimestamps) { // always try to rebuild in case of an error - if(this.error) return true; + if (this.error) return true; // always rebuild when module is not cacheable - if(!this.buildInfo.cacheable) return true; + if (!this.buildInfo.cacheable) return true; // Check timestamps of all dependencies // Missing timestamp -> need rebuild // Timestamp bigger than buildTimestamp -> need rebuild - for(const file of this.buildInfo.fileDependencies) { + for (const file of this.buildInfo.fileDependencies) { const timestamp = fileTimestamps.get(file); - if(!timestamp) return true; - if(timestamp >= this.buildTimestamp) return true; + if (!timestamp) return true; + if (timestamp >= this.buildTimestamp) return true; } - for(const file of this.buildInfo.contextDependencies) { + for (const file of this.buildInfo.contextDependencies) { const timestamp = contextTimestamps.get(file); - if(!timestamp) return true; - if(timestamp >= this.buildTimestamp) return true; + if (!timestamp) return true; + if (timestamp >= this.buildTimestamp) return true; } // elsewise -> no rebuild needed return false; @@ -410,7 +447,7 @@ class NormalModule extends Module { } updateHashWithSource(hash) { - if(!this._source) { + if (!this._source) { hash.update("null"); return; } @@ -428,7 +465,6 @@ class NormalModule extends Module { this.updateHashWithMeta(hash); super.updateHash(hash); } - } module.exports = NormalModule; diff --git a/lib/NormalModuleFactory.js b/lib/NormalModuleFactory.js index df3f844a8..147bfaae3 100644 --- a/lib/NormalModuleFactory.js +++ b/lib/NormalModuleFactory.js @@ -19,14 +19,11 @@ const cachedMerge = require("./util/cachedMerge"); const EMPTY_RESOLVE_OPTIONS = {}; const loaderToIdent = data => { - if(!data.options) - return data.loader; - if(typeof data.options === "string") - return data.loader + "?" + data.options; - if(typeof data.options !== "object") + if (!data.options) return data.loader; + if (typeof data.options === "string") return data.loader + "?" + data.options; + if (typeof data.options !== "object") throw new Error("loader options must be string or object"); - if(data.ident) - return data.loader + "??" + data.ident; + if (data.ident) return data.loader + "??" + data.ident; return data.loader + "?" + JSON.stringify(data.options); }; @@ -34,7 +31,7 @@ const identToLoaderRequest = resultString => { const idx = resultString.indexOf("?"); let options; - if(idx >= 0) { + if (idx >= 0) { options = resultString.substr(idx + 1); resultString = resultString.substr(0, idx); @@ -61,34 +58,53 @@ class NormalModuleFactory extends Tapable { module: new SyncWaterfallHook(["module", "data"]), createParser: new HookMap(() => new SyncBailHook(["parserOptions"])), parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])), - createGenerator: new HookMap(() => new SyncBailHook(["generatorOptions"])), - generator: new HookMap(() => new SyncHook(["generator", "generatorOptions"])), + createGenerator: new HookMap( + () => new SyncBailHook(["generatorOptions"]) + ), + generator: new HookMap( + () => new SyncHook(["generator", "generatorOptions"]) + ) }; this._pluginCompat.tap("NormalModuleFactory", options => { - switch(options.name) { + switch (options.name) { case "before-resolve": case "after-resolve": options.async = true; break; case "parser": - this.hooks.parser.for("javascript/auto").tap(options.fn.name || "unnamed compat plugin", options.fn); + this.hooks.parser + .for("javascript/auto") + .tap(options.fn.name || "unnamed compat plugin", options.fn); return true; } let match; match = /^parser (.+)$/.exec(options.name); - if(match) { - this.hooks.parser.for(match[1]).tap(options.fn.name || "unnamed compat plugin", options.fn.bind(this)); + if (match) { + this.hooks.parser + .for(match[1]) + .tap( + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); return true; } match = /^create-parser (.+)$/.exec(options.name); - if(match) { - this.hooks.createParser.for(match[1]).tap(options.fn.name || "unnamed compat plugin", options.fn.bind(this)); + if (match) { + this.hooks.createParser + .for(match[1]) + .tap( + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); return true; } }); this.resolverFactory = resolverFactory; this.ruleSet = new RuleSet(options.defaultRules.concat(options.rules)); - this.cachePredicate = typeof options.unsafeCache === "function" ? options.unsafeCache : Boolean.bind(null, options.unsafeCache); + this.cachePredicate = + typeof options.unsafeCache === "function" + ? options.unsafeCache + : Boolean.bind(null, options.unsafeCache); this.context = context || ""; this.parserCache = Object.create(null); this.generatorCache = Object.create(null); @@ -96,28 +112,26 @@ class NormalModuleFactory extends Tapable { let resolver = this.hooks.resolver.call(null); // Ignored - if(!resolver) return callback(); + if (!resolver) return callback(); resolver(result, (err, data) => { - if(err) return callback(err); + if (err) return callback(err); // Ignored - if(!data) return callback(); + if (!data) return callback(); // direct module - if(typeof data.source === "function") - return callback(null, data); + if (typeof data.source === "function") return callback(null, data); this.hooks.afterResolve.callAsync(data, (err, result) => { - if(err) return callback(err); + if (err) return callback(err); // Ignored - if(!result) return callback(); + if (!result) return callback(); let createdModule = this.hooks.createModule.call(result); - if(!createdModule) { - - if(!result.request) { + if (!createdModule) { + if (!result.request) { return callback(new Error("Empty dependency (no request)")); } @@ -138,206 +152,292 @@ class NormalModuleFactory extends Tapable { const noPreAutoLoaders = request.startsWith("-!"); const noAutoLoaders = noPreAutoLoaders || request.startsWith("!"); const noPrePostAutoLoaders = request.startsWith("!!"); - let elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!"); + let elements = request + .replace(/^-?!+/, "") + .replace(/!!+/g, "!") + .split("!"); let resource = elements.pop(); elements = elements.map(identToLoaderRequest); const loaderResolver = this.getResolver("loader"); const normalResolver = this.getResolver("normal", data.resolveOptions); - asyncLib.parallel([ - callback => this.resolveRequestArray(contextInfo, context, elements, loaderResolver, callback), - callback => { - if(resource === "" || resource[0] === "?") { - return callback(null, { - resource - }); + asyncLib.parallel( + [ + callback => + this.resolveRequestArray( + contextInfo, + context, + elements, + loaderResolver, + callback + ), + callback => { + if (resource === "" || resource[0] === "?") { + return callback(null, { + resource + }); + } + + normalResolver.resolve( + contextInfo, + context, + resource, + {}, + (err, resource, resourceResolveData) => { + if (err) return callback(err); + callback(null, { + resourceResolveData, + resource + }); + } + ); + } + ], + (err, results) => { + if (err) return callback(err); + let loaders = results[0]; + const resourceResolveData = results[1].resourceResolveData; + resource = results[1].resource; + + // translate option idents + try { + for (const item of loaders) { + if (typeof item.options === "string" && item.options[0] === "?") { + const ident = item.options.substr(1); + item.options = this.ruleSet.findOptionsByIdent(ident); + item.ident = ident; + } + } + } catch (e) { + return callback(e); } - normalResolver.resolve(contextInfo, context, resource, {}, (err, resource, resourceResolveData) => { - if(err) return callback(err); - callback(null, { - resourceResolveData, - resource - }); - }); - } - ], (err, results) => { - if(err) return callback(err); - let loaders = results[0]; - const resourceResolveData = results[1].resourceResolveData; - resource = results[1].resource; + if (resource === false) { + // ignored + return callback( + null, + new RawModule( + "/* (ignored) */", + `ignored ${context} ${request}`, + `${request} (ignored)` + ) + ); + } - // translate option idents - try { - for(const item of loaders) { - if(typeof item.options === "string" && item.options[0] === "?") { - const ident = item.options.substr(1); - item.options = this.ruleSet.findOptionsByIdent(ident); - item.ident = ident; + const userRequest = loaders + .map(loaderToIdent) + .concat([resource]) + .join("!"); + + let resourcePath = resource; + let resourceQuery = ""; + const queryIndex = resourcePath.indexOf("?"); + if (queryIndex >= 0) { + resourceQuery = resourcePath.substr(queryIndex); + resourcePath = resourcePath.substr(0, queryIndex); + } + + const result = this.ruleSet.exec({ + resource: resourcePath, + resourceQuery, + issuer: contextInfo.issuer, + compiler: contextInfo.compiler + }); + const settings = {}; + const useLoadersPost = []; + const useLoaders = []; + const useLoadersPre = []; + for (const r of result) { + if (r.type === "use") { + if (r.enforce === "post" && !noPrePostAutoLoaders) + useLoadersPost.push(r.value); + else if ( + r.enforce === "pre" && + !noPreAutoLoaders && + !noPrePostAutoLoaders + ) + useLoadersPre.push(r.value); + else if (!r.enforce && !noAutoLoaders && !noPrePostAutoLoaders) + useLoaders.push(r.value); + } else if ( + typeof r.value === "object" && + r.value !== null && + typeof settings[r.type] === "object" && + settings[r.type] !== null + ) { + settings[r.type] = cachedMerge(settings[r.type], r.value); + } else { + settings[r.type] = r.value; } } - } catch(e) { - return callback(e); - } - - if(resource === false) { - // ignored - return callback(null, - new RawModule( - "/* (ignored) */", - `ignored ${context} ${request}`, - `${request} (ignored)` - ) + asyncLib.parallel( + [ + this.resolveRequestArray.bind( + this, + contextInfo, + this.context, + useLoadersPost, + loaderResolver + ), + this.resolveRequestArray.bind( + this, + contextInfo, + this.context, + useLoaders, + loaderResolver + ), + this.resolveRequestArray.bind( + this, + contextInfo, + this.context, + useLoadersPre, + loaderResolver + ) + ], + (err, results) => { + if (err) return callback(err); + loaders = results[0].concat(loaders, results[1], results[2]); + process.nextTick(() => { + const type = settings.type; + const resolveOptions = settings.resolve; + callback(null, { + context: context, + request: loaders + .map(loaderToIdent) + .concat([resource]) + .join("!"), + dependencies: data.dependencies, + userRequest, + rawRequest: request, + loaders, + resource, + resourceResolveData, + settings, + type, + parser: this.getParser(type, settings.parser), + generator: this.getGenerator(type, settings.generator), + resolveOptions + }); + }); + } ); } - - const userRequest = loaders.map(loaderToIdent).concat([resource]).join("!"); - - let resourcePath = resource; - let resourceQuery = ""; - const queryIndex = resourcePath.indexOf("?"); - if(queryIndex >= 0) { - resourceQuery = resourcePath.substr(queryIndex); - resourcePath = resourcePath.substr(0, queryIndex); - } - - const result = this.ruleSet.exec({ - resource: resourcePath, - resourceQuery, - issuer: contextInfo.issuer, - compiler: contextInfo.compiler - }); - const settings = {}; - const useLoadersPost = []; - const useLoaders = []; - const useLoadersPre = []; - for(const r of result) { - if(r.type === "use") { - if(r.enforce === "post" && !noPrePostAutoLoaders) - useLoadersPost.push(r.value); - else if(r.enforce === "pre" && !noPreAutoLoaders && !noPrePostAutoLoaders) - useLoadersPre.push(r.value); - else if(!r.enforce && !noAutoLoaders && !noPrePostAutoLoaders) - useLoaders.push(r.value); - } else if(typeof r.value === "object" && r.value !== null && typeof settings[r.type] === "object" && settings[r.type] !== null) { - settings[r.type] = cachedMerge(settings[r.type], r.value); - } else { - settings[r.type] = r.value; - } - } - asyncLib.parallel([ - this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPost, loaderResolver), - this.resolveRequestArray.bind(this, contextInfo, this.context, useLoaders, loaderResolver), - this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPre, loaderResolver) - ], (err, results) => { - if(err) return callback(err); - loaders = results[0].concat(loaders, results[1], results[2]); - process.nextTick(() => { - const type = settings.type; - const resolveOptions = settings.resolve; - callback(null, { - context: context, - request: loaders.map(loaderToIdent).concat([resource]).join("!"), - dependencies: data.dependencies, - userRequest, - rawRequest: request, - loaders, - resource, - resourceResolveData, - settings, - type, - parser: this.getParser(type, settings.parser), - generator: this.getGenerator(type, settings.generator), - resolveOptions - }); - }); - }); - }); + ); }); } create(data, callback) { const dependencies = data.dependencies; const cacheEntry = dependencies[0].__NormalModuleFactoryCache; - if(cacheEntry) return callback(null, cacheEntry); + if (cacheEntry) return callback(null, cacheEntry); const context = data.context || this.context; const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS; const request = dependencies[0].request; const contextInfo = data.contextInfo || {}; - this.hooks.beforeResolve.callAsync({ - contextInfo, - resolveOptions, - context, - request, - dependencies - }, (err, result) => { - if(err) return callback(err); + this.hooks.beforeResolve.callAsync( + { + contextInfo, + resolveOptions, + context, + request, + dependencies + }, + (err, result) => { + if (err) return callback(err); - // Ignored - if(!result) return callback(); + // Ignored + if (!result) return callback(); - const factory = this.hooks.factory.call(null); + const factory = this.hooks.factory.call(null); - // Ignored - if(!factory) return callback(); + // Ignored + if (!factory) return callback(); - factory(result, (err, module) => { - if(err) return callback(err); + factory(result, (err, module) => { + if (err) return callback(err); - if(module && this.cachePredicate(module)) { - for(const d of dependencies) { - d.__NormalModuleFactoryCache = module; + if (module && this.cachePredicate(module)) { + for (const d of dependencies) { + d.__NormalModuleFactoryCache = module; + } } - } - callback(null, module); - }); - }); + callback(null, module); + }); + } + ); } resolveRequestArray(contextInfo, context, array, resolver, callback) { - if(array.length === 0) return callback(null, []); - asyncLib.map(array, (item, callback) => { - resolver.resolve(contextInfo, context, item.loader, {}, (err, result) => { - if(err && /^[^/]*$/.test(item.loader) && !/-loader$/.test(item.loader)) { - return resolver.resolve(contextInfo, context, item.loader + "-loader", {}, err2 => { - if(!err2) { - err.message = err.message + "\n" + - "BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" + - ` You need to specify '${item.loader}-loader' instead of '${item.loader}',\n` + - " see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed"; + if (array.length === 0) return callback(null, []); + asyncLib.map( + array, + (item, callback) => { + resolver.resolve( + contextInfo, + context, + item.loader, + {}, + (err, result) => { + if ( + err && + /^[^/]*$/.test(item.loader) && + !/-loader$/.test(item.loader) + ) { + return resolver.resolve( + contextInfo, + context, + item.loader + "-loader", + {}, + err2 => { + if (!err2) { + err.message = + err.message + + "\n" + + "BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" + + ` You need to specify '${ + item.loader + }-loader' instead of '${item.loader}',\n` + + " see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed"; + } + callback(err); + } + ); } - callback(err); - }); - } - if(err) return callback(err); + if (err) return callback(err); - const optionsOnly = item.options ? { - options: item.options - } : undefined; - return callback(null, Object.assign({}, item, identToLoaderRequest(result), optionsOnly)); - }); - }, callback); + const optionsOnly = item.options + ? { + options: item.options + } + : undefined; + return callback( + null, + Object.assign({}, item, identToLoaderRequest(result), optionsOnly) + ); + } + ); + }, + callback + ); } getParser(type, parserOptions) { let ident = type; - if(parserOptions) { - if(parserOptions.ident) - ident = `${type}|${parserOptions.ident}`; - else - ident = JSON.stringify([type, parserOptions]); + if (parserOptions) { + if (parserOptions.ident) ident = `${type}|${parserOptions.ident}`; + else ident = JSON.stringify([type, parserOptions]); } - if(ident in this.parserCache) { + if (ident in this.parserCache) { return this.parserCache[ident]; } - return this.parserCache[ident] = this.createParser(type, parserOptions); + return (this.parserCache[ident] = this.createParser(type, parserOptions)); } createParser(type, parserOptions = {}) { const parser = this.hooks.createParser.for(type).call(parserOptions); - if(!parser) { + if (!parser) { throw new Error(`No parser registered for ${type}`); } this.hooks.parser.for(type).call(parser, parserOptions); @@ -346,21 +446,24 @@ class NormalModuleFactory extends Tapable { getGenerator(type, generatorOptions) { let ident = type; - if(generatorOptions) { - if(generatorOptions.ident) - ident = `${type}|${generatorOptions.ident}`; - else - ident = JSON.stringify([type, generatorOptions]); + if (generatorOptions) { + if (generatorOptions.ident) ident = `${type}|${generatorOptions.ident}`; + else ident = JSON.stringify([type, generatorOptions]); } - if(ident in this.generatorCache) { + if (ident in this.generatorCache) { return this.generatorCache[ident]; } - return this.generatorCache[ident] = this.createGenerator(type, generatorOptions); + return (this.generatorCache[ident] = this.createGenerator( + type, + generatorOptions + )); } createGenerator(type, generatorOptions = {}) { - const generator = this.hooks.createGenerator.for(type).call(generatorOptions); - if(!generator) { + const generator = this.hooks.createGenerator + .for(type) + .call(generatorOptions); + if (!generator) { throw new Error(`No generator registered for ${type}`); } this.hooks.generator.for(type).call(generator, generatorOptions); @@ -368,7 +471,10 @@ class NormalModuleFactory extends Tapable { } getResolver(type, resolveOptions) { - return this.resolverFactory.get(type, resolveOptions || EMPTY_RESOLVE_OPTIONS); + return this.resolverFactory.get( + type, + resolveOptions || EMPTY_RESOLVE_OPTIONS + ); } } diff --git a/lib/NormalModuleReplacementPlugin.js b/lib/NormalModuleReplacementPlugin.js index 531795765..d4f23a58b 100644 --- a/lib/NormalModuleReplacementPlugin.js +++ b/lib/NormalModuleReplacementPlugin.js @@ -15,30 +15,36 @@ class NormalModuleReplacementPlugin { apply(compiler) { const resourceRegExp = this.resourceRegExp; const newResource = this.newResource; - compiler.hooks.normalModuleFactory.tap("NormalModuleReplacementPlugin", (nmf) => { - nmf.hooks.beforeResolve.tap("NormalModuleReplacementPlugin", (result) => { - if(!result) return; - if(resourceRegExp.test(result.request)) { - if(typeof newResource === "function") { - newResource(result); - } else { - result.request = newResource; + compiler.hooks.normalModuleFactory.tap( + "NormalModuleReplacementPlugin", + nmf => { + nmf.hooks.beforeResolve.tap("NormalModuleReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.request)) { + if (typeof newResource === "function") { + newResource(result); + } else { + result.request = newResource; + } } - } - return result; - }); - nmf.hooks.afterResolve.tap("NormalModuleReplacementPlugin", (result) => { - if(!result) return; - if(resourceRegExp.test(result.resource)) { - if(typeof newResource === "function") { - newResource(result); - } else { - result.resource = path.resolve(path.dirname(result.resource), newResource); + return result; + }); + nmf.hooks.afterResolve.tap("NormalModuleReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.resource)) { + if (typeof newResource === "function") { + newResource(result); + } else { + result.resource = path.resolve( + path.dirname(result.resource), + newResource + ); + } } - } - return result; - }); - }); + return result; + }); + } + ); } } diff --git a/lib/OptionsDefaulter.js b/lib/OptionsDefaulter.js index bb451cc94..2dba587bc 100644 --- a/lib/OptionsDefaulter.js +++ b/lib/OptionsDefaulter.js @@ -6,19 +6,20 @@ const getProperty = (obj, name) => { name = name.split("."); - for(let i = 0; i < name.length - 1; i++) { + for (let i = 0; i < name.length - 1; i++) { obj = obj[name[i]]; - if(typeof obj !== "object" || !obj || Array.isArray(obj)) return; + if (typeof obj !== "object" || !obj || Array.isArray(obj)) return; } return obj[name.pop()]; }; const setProperty = (obj, name, value) => { name = name.split("."); - for(let i = 0; i < name.length - 1; i++) { - if(typeof obj[name[i]] !== "object" && typeof obj[name[i]] !== "undefined") return; - if(Array.isArray(obj[name[i]])) return; - if(!obj[name[i]]) obj[name[i]] = {}; + for (let i = 0; i < name.length - 1; i++) { + if (typeof obj[name[i]] !== "object" && typeof obj[name[i]] !== "undefined") + return; + if (Array.isArray(obj[name[i]])) return; + if (!obj[name[i]]) obj[name[i]] = {}; obj = obj[name[i]]; } obj[name.pop()] = value; @@ -32,36 +33,47 @@ class OptionsDefaulter { process(options) { options = Object.assign({}, options); - for(let name in this.defaults) { - switch(this.config[name]) { + for (let name in this.defaults) { + switch (this.config[name]) { case undefined: - if(getProperty(options, name) === undefined) + if (getProperty(options, name) === undefined) setProperty(options, name, this.defaults[name]); break; case "call": - setProperty(options, name, this.defaults[name].call(this, getProperty(options, name), options), options); + setProperty( + options, + name, + this.defaults[name].call(this, getProperty(options, name), options), + options + ); break; case "make": - if(getProperty(options, name) === undefined) - setProperty(options, name, this.defaults[name].call(this, options), options); + if (getProperty(options, name) === undefined) + setProperty( + options, + name, + this.defaults[name].call(this, options), + options + ); break; - case "append": - { - let oldValue = getProperty(options, name); - if(!Array.isArray(oldValue)) oldValue = []; - oldValue.push(...this.defaults[name]); - setProperty(options, name, oldValue); - break; - } + case "append": { + let oldValue = getProperty(options, name); + if (!Array.isArray(oldValue)) oldValue = []; + oldValue.push(...this.defaults[name]); + setProperty(options, name, oldValue); + break; + } default: - throw new Error("OptionsDefaulter cannot process " + this.config[name]); + throw new Error( + "OptionsDefaulter cannot process " + this.config[name] + ); } } return options; } set(name, config, def) { - if(def !== undefined) { + if (def !== undefined) { this.defaults[name] = def; this.config[name] = config; } else { diff --git a/lib/Parser.js b/lib/Parser.js index 5bda48f2e..da8fe4bf8 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -16,8 +16,8 @@ const StackedSetMap = require("./util/StackedSetMap"); const TrackingSet = require("./util/TrackingSet"); const joinRanges = (startRange, endRange) => { - if(!endRange) return startRange; - if(!startRange) return endRange; + if (!endRange) return startRange; + if (!startRange) return endRange; return [startRange[0], endRange[1]]; }; @@ -39,19 +39,39 @@ class Parser extends Tapable { evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])), evaluate: new HookMap(() => new SyncBailHook(["expression"])), evaluateIdentifier: new HookMap(() => new SyncBailHook(["expression"])), - evaluateDefinedIdentifier: new HookMap(() => new SyncBailHook(["expression"])), - evaluateCallExpressionMember: new HookMap(() => new SyncBailHook(["expression", "param"])), + evaluateDefinedIdentifier: new HookMap( + () => new SyncBailHook(["expression"]) + ), + evaluateCallExpressionMember: new HookMap( + () => new SyncBailHook(["expression", "param"]) + ), statement: new SyncBailHook(["statement"]), statementIf: new SyncBailHook(["statement"]), label: new HookMap(() => new SyncBailHook(["statement"])), import: new SyncBailHook(["statement", "source"]), - importSpecifier: new SyncBailHook(["statement", "source", "exportName", "identifierName"]), + importSpecifier: new SyncBailHook([ + "statement", + "source", + "exportName", + "identifierName" + ]), export: new SyncBailHook(["statement"]), exportImport: new SyncBailHook(["statement", "source"]), exportDeclaration: new SyncBailHook(["statement", "declaration"]), exportExpression: new SyncBailHook(["statement", "declaration"]), - exportSpecifier: new SyncBailHook(["statement", "identifierName", "exportName", "index"]), - exportImportSpecifier: new SyncBailHook(["statement", "source", "identifierName", "exportName", "index"]), + exportSpecifier: new SyncBailHook([ + "statement", + "identifierName", + "exportName", + "index" + ]), + exportImportSpecifier: new SyncBailHook([ + "statement", + "source", + "identifierName", + "exportName", + "index" + ]), varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])), varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])), varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])), @@ -68,7 +88,7 @@ class Parser extends Tapable { expression: new HookMap(() => new SyncBailHook(["expression"])), expressionAnyMember: new HookMap(() => new SyncBailHook(["expression"])), expressionConditionalOperator: new SyncBailHook(["expression"]), - program: new SyncBailHook(["ast", "comments"]), + program: new SyncBailHook(["ast", "comments"]) }; const HOOK_MAP_COMPAT_CONFIG = { evaluateTypeof: /^evaluate typeof (.+)$/, @@ -91,17 +111,24 @@ class Parser extends Tapable { new: /^new (.+)$/, expressionConditionalOperator: /^expression \?:$/, expressionAnyMember: /^expression (.+)\.\*$/, - expression: /^expression (.+)$/, + expression: /^expression (.+)$/ }; this._pluginCompat.tap("Parser", options => { - for(const name of Object.keys(HOOK_MAP_COMPAT_CONFIG)) { + for (const name of Object.keys(HOOK_MAP_COMPAT_CONFIG)) { const regexp = HOOK_MAP_COMPAT_CONFIG[name]; const match = regexp.exec(options.name); - if(match) { - if(match[1]) - this.hooks[name].tap(match[1], options.fn.name || "unnamed compat plugin", options.fn.bind(this)); + if (match) { + if (match[1]) + this.hooks[name].tap( + match[1], + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); else - this.hooks[name].tap(options.fn.name || "unnamed compat plugin", options.fn.bind(this)); + this.hooks[name].tap( + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); return true; } } @@ -116,35 +143,43 @@ class Parser extends Tapable { initializeEvaluating() { this.hooks.evaluate.for("Literal").tap("Parser", expr => { - switch(typeof expr.value) { + switch (typeof expr.value) { case "number": - return new BasicEvaluatedExpression().setNumber(expr.value).setRange(expr.range); + return new BasicEvaluatedExpression() + .setNumber(expr.value) + .setRange(expr.range); case "string": - return new BasicEvaluatedExpression().setString(expr.value).setRange(expr.range); + return new BasicEvaluatedExpression() + .setString(expr.value) + .setRange(expr.range); case "boolean": - return new BasicEvaluatedExpression().setBoolean(expr.value).setRange(expr.range); + return new BasicEvaluatedExpression() + .setBoolean(expr.value) + .setRange(expr.range); } - if(expr.value === null) + if (expr.value === null) return new BasicEvaluatedExpression().setNull().setRange(expr.range); - if(expr.value instanceof RegExp) - return new BasicEvaluatedExpression().setRegExp(expr.value).setRange(expr.range); + if (expr.value instanceof RegExp) + return new BasicEvaluatedExpression() + .setRegExp(expr.value) + .setRange(expr.range); }); this.hooks.evaluate.for("LogicalExpression").tap("Parser", expr => { let left; let leftAsBool; let right; - if(expr.operator === "&&") { + if (expr.operator === "&&") { left = this.evaluateExpression(expr.left); leftAsBool = left && left.asBool(); - if(leftAsBool === false) return left.setRange(expr.range); - if(leftAsBool !== true) return; + if (leftAsBool === false) return left.setRange(expr.range); + if (leftAsBool !== true) return; right = this.evaluateExpression(expr.right); return right.setRange(expr.range); - } else if(expr.operator === "||") { + } else if (expr.operator === "||") { left = this.evaluateExpression(expr.left); leftAsBool = left && left.asBool(); - if(leftAsBool === true) return left.setRange(expr.range); - if(leftAsBool !== false) return; + if (leftAsBool === true) return left.setRange(expr.range); + if (leftAsBool !== false) return; right = this.evaluateExpression(expr.right); return right.setRange(expr.range); } @@ -153,179 +188,193 @@ class Parser extends Tapable { let left; let right; let res; - if(expr.operator === "+") { + if (expr.operator === "+") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; + if (!left || !right) return; res = new BasicEvaluatedExpression(); - if(left.isString()) { - if(right.isString()) { + if (left.isString()) { + if (right.isString()) { res.setString(left.string + right.string); - } else if(right.isNumber()) { + } else if (right.isNumber()) { res.setString(left.string + right.number); - } else if(right.isWrapped() && right.prefix && right.prefix.isString()) { + } else if ( + right.isWrapped() && + right.prefix && + right.prefix.isString() + ) { res.setWrapped( new BasicEvaluatedExpression() - .setString(left.string + right.prefix.string) - .setRange(joinRanges(left.range, right.prefix.range)), - right.postfix); - } else if(right.isWrapped()) { + .setString(left.string + right.prefix.string) + .setRange(joinRanges(left.range, right.prefix.range)), + right.postfix + ); + } else if (right.isWrapped()) { res.setWrapped( new BasicEvaluatedExpression() - .setString(left.string) - .setRange(left.range), - right.postfix); + .setString(left.string) + .setRange(left.range), + right.postfix + ); } else { res.setWrapped(left, null); } - } else if(left.isNumber()) { - if(right.isString()) { + } else if (left.isNumber()) { + if (right.isString()) { res.setString(left.number + right.string); - } else if(right.isNumber()) { + } else if (right.isNumber()) { res.setNumber(left.number + right.number); } - } else if(left.isWrapped()) { - if(left.postfix && left.postfix.isString() && right.isString()) { - res.setWrapped(left.prefix, + } else if (left.isWrapped()) { + if (left.postfix && left.postfix.isString() && right.isString()) { + res.setWrapped( + left.prefix, new BasicEvaluatedExpression() - .setString(left.postfix.string + right.string) - .setRange(joinRanges(left.postfix.range, right.range)) + .setString(left.postfix.string + right.string) + .setRange(joinRanges(left.postfix.range, right.range)) ); - } else if(left.postfix && left.postfix.isString() && right.isNumber()) { - res.setWrapped(left.prefix, + } else if ( + left.postfix && + left.postfix.isString() && + right.isNumber() + ) { + res.setWrapped( + left.prefix, new BasicEvaluatedExpression() - .setString(left.postfix.string + right.number) - .setRange(joinRanges(left.postfix.range, right.range)) + .setString(left.postfix.string + right.number) + .setRange(joinRanges(left.postfix.range, right.range)) ); - } else if(right.isString()) { + } else if (right.isString()) { res.setWrapped(left.prefix, right); - } else if(right.isNumber()) { - res.setWrapped(left.prefix, + } else if (right.isNumber()) { + res.setWrapped( + left.prefix, new BasicEvaluatedExpression() - .setString(right.number + "") - .setRange(right.range)); + .setString(right.number + "") + .setRange(right.range) + ); } else { res.setWrapped(left.prefix, new BasicEvaluatedExpression()); } } else { - if(right.isString()) { + if (right.isString()) { res.setWrapped(null, right); } } res.setRange(expr.range); return res; - } else if(expr.operator === "-") { + } else if (expr.operator === "-") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number - right.number); res.setRange(expr.range); return res; - } else if(expr.operator === "*") { + } else if (expr.operator === "*") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number * right.number); res.setRange(expr.range); return res; - } else if(expr.operator === "/") { + } else if (expr.operator === "/") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number / right.number); res.setRange(expr.range); return res; - } else if(expr.operator === "**") { + } else if (expr.operator === "**") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(Math.pow(left.number, right.number)); res.setRange(expr.range); return res; - } else if(expr.operator === "==" || expr.operator === "===") { + } else if (expr.operator === "==" || expr.operator === "===") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; + if (!left || !right) return; res = new BasicEvaluatedExpression(); res.setRange(expr.range); - if(left.isString() && right.isString()) { + if (left.isString() && right.isString()) { return res.setBoolean(left.string === right.string); - } else if(left.isNumber() && right.isNumber()) { + } else if (left.isNumber() && right.isNumber()) { return res.setBoolean(left.number === right.number); - } else if(left.isBoolean() && right.isBoolean()) { + } else if (left.isBoolean() && right.isBoolean()) { return res.setBoolean(left.bool === right.bool); } - } else if(expr.operator === "!=" || expr.operator === "!==") { + } else if (expr.operator === "!=" || expr.operator === "!==") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; + if (!left || !right) return; res = new BasicEvaluatedExpression(); res.setRange(expr.range); - if(left.isString() && right.isString()) { + if (left.isString() && right.isString()) { return res.setBoolean(left.string !== right.string); - } else if(left.isNumber() && right.isNumber()) { + } else if (left.isNumber() && right.isNumber()) { return res.setBoolean(left.number !== right.number); - } else if(left.isBoolean() && right.isBoolean()) { + } else if (left.isBoolean() && right.isBoolean()) { return res.setBoolean(left.bool !== right.bool); } - } else if(expr.operator === "&") { + } else if (expr.operator === "&") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number & right.number); res.setRange(expr.range); return res; - } else if(expr.operator === "|") { + } else if (expr.operator === "|") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number | right.number); res.setRange(expr.range); return res; - } else if(expr.operator === "^") { + } else if (expr.operator === "^") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number ^ right.number); res.setRange(expr.range); return res; - } else if(expr.operator === ">>>") { + } else if (expr.operator === ">>>") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number >>> right.number); res.setRange(expr.range); return res; - } else if(expr.operator === ">>") { + } else if (expr.operator === ">>") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number >> right.number); res.setRange(expr.range); return res; - } else if(expr.operator === "<<") { + } else if (expr.operator === "<<") { left = this.evaluateExpression(expr.left); right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; res = new BasicEvaluatedExpression(); res.setNumber(left.number << right.number); res.setRange(expr.range); @@ -333,55 +382,80 @@ class Parser extends Tapable { } }); this.hooks.evaluate.for("UnaryExpression").tap("Parser", expr => { - if(expr.operator === "typeof") { + if (expr.operator === "typeof") { let res; let name; - if(expr.argument.type === "Identifier") { - name = this.scope.renames.get(expr.argument.name) || expr.argument.name; - if(!this.scope.definitions.has(name)) { + if (expr.argument.type === "Identifier") { + name = + this.scope.renames.get(expr.argument.name) || expr.argument.name; + if (!this.scope.definitions.has(name)) { const hook = this.hooks.evaluateTypeof.get(name); - if(hook !== undefined) { + if (hook !== undefined) { res = hook.call(expr); - if(res !== undefined) return res; + if (res !== undefined) return res; } } } - if(expr.argument.type === "MemberExpression") { + if (expr.argument.type === "MemberExpression") { const exprName = this.getNameForExpression(expr.argument); - if(exprName && exprName.free) { + if (exprName && exprName.free) { const hook = this.hooks.evaluateTypeof.get(exprName.name); - if(hook !== undefined) { + if (hook !== undefined) { res = hook.call(expr); - if(res !== undefined) return res; + if (res !== undefined) return res; } } } - if(expr.argument.type === "FunctionExpression") { - return new BasicEvaluatedExpression().setString("function").setRange(expr.range); + if (expr.argument.type === "FunctionExpression") { + return new BasicEvaluatedExpression() + .setString("function") + .setRange(expr.range); } const arg = this.evaluateExpression(expr.argument); - if(arg.isString() || arg.isWrapped()) return new BasicEvaluatedExpression().setString("string").setRange(expr.range); - else if(arg.isNumber()) return new BasicEvaluatedExpression().setString("number").setRange(expr.range); - else if(arg.isBoolean()) return new BasicEvaluatedExpression().setString("boolean").setRange(expr.range); - else if(arg.isArray() || arg.isConstArray() || arg.isRegExp()) return new BasicEvaluatedExpression().setString("object").setRange(expr.range); - } else if(expr.operator === "!") { + if (arg.isString() || arg.isWrapped()) + return new BasicEvaluatedExpression() + .setString("string") + .setRange(expr.range); + else if (arg.isNumber()) + return new BasicEvaluatedExpression() + .setString("number") + .setRange(expr.range); + else if (arg.isBoolean()) + return new BasicEvaluatedExpression() + .setString("boolean") + .setRange(expr.range); + else if (arg.isArray() || arg.isConstArray() || arg.isRegExp()) + return new BasicEvaluatedExpression() + .setString("object") + .setRange(expr.range); + } else if (expr.operator === "!") { const argument = this.evaluateExpression(expr.argument); - if(!argument) return; - if(argument.isBoolean()) { - return new BasicEvaluatedExpression().setBoolean(!argument.bool).setRange(expr.range); - } else if(argument.isTruthy()) { - return new BasicEvaluatedExpression().setBoolean(false).setRange(expr.range); - } else if(argument.isFalsy()) { - return new BasicEvaluatedExpression().setBoolean(true).setRange(expr.range); - } else if(argument.isString()) { - return new BasicEvaluatedExpression().setBoolean(!argument.string).setRange(expr.range); - } else if(argument.isNumber()) { - return new BasicEvaluatedExpression().setBoolean(!argument.number).setRange(expr.range); + if (!argument) return; + if (argument.isBoolean()) { + return new BasicEvaluatedExpression() + .setBoolean(!argument.bool) + .setRange(expr.range); + } else if (argument.isTruthy()) { + return new BasicEvaluatedExpression() + .setBoolean(false) + .setRange(expr.range); + } else if (argument.isFalsy()) { + return new BasicEvaluatedExpression() + .setBoolean(true) + .setRange(expr.range); + } else if (argument.isString()) { + return new BasicEvaluatedExpression() + .setBoolean(!argument.string) + .setRange(expr.range); + } else if (argument.isNumber()) { + return new BasicEvaluatedExpression() + .setBoolean(!argument.number) + .setRange(expr.range); } - } else if(expr.operator === "~") { + } else if (expr.operator === "~") { const argument = this.evaluateExpression(expr.argument); - if(!argument) return; - if(!argument.isNumber()) return; + if (!argument) return; + if (!argument.isNumber()) return; const res = new BasicEvaluatedExpression(); res.setNumber(~argument.number); res.setRange(expr.range); @@ -389,100 +463,120 @@ class Parser extends Tapable { } }); this.hooks.evaluateTypeof.for("undefined").tap("Parser", expr => { - return new BasicEvaluatedExpression().setString("undefined").setRange(expr.range); + return new BasicEvaluatedExpression() + .setString("undefined") + .setRange(expr.range); }); this.hooks.evaluate.for("Identifier").tap("Parser", expr => { const name = this.scope.renames.get(expr.name) || expr.name; - if(!this.scope.definitions.has(expr.name)) { + if (!this.scope.definitions.has(expr.name)) { const hook = this.hooks.evaluateIdentifier.get(name); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(expr); - if(result) return result; + if (result) return result; } - return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range); + return new BasicEvaluatedExpression() + .setIdentifier(name) + .setRange(expr.range); } else { const hook = this.hooks.evaluateDefinedIdentifier.get(name); - if(hook !== undefined) { + if (hook !== undefined) { return hook.call(expr); } } }); this.hooks.evaluate.for("ThisExpression").tap("Parser", expr => { const name = this.scope.renames.get("this"); - if(name) { + if (name) { const hook = this.hooks.evaluateIdentifier.get(name); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(expr); - if(result) return result; + if (result) return result; } - return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range); + return new BasicEvaluatedExpression() + .setIdentifier(name) + .setRange(expr.range); } }); this.hooks.evaluate.for("MemberExpression").tap("Parser", expression => { let exprName = this.getNameForExpression(expression); - if(exprName) { - if(exprName.free) { + if (exprName) { + if (exprName.free) { const hook = this.hooks.evaluateIdentifier.get(exprName.name); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(expression); - if(result) return result; + if (result) return result; } - return new BasicEvaluatedExpression().setIdentifier(exprName.name).setRange(expression.range); + return new BasicEvaluatedExpression() + .setIdentifier(exprName.name) + .setRange(expression.range); } else { const hook = this.hooks.evaluateDefinedIdentifier.get(exprName.name); - if(hook !== undefined) { + if (hook !== undefined) { return hook.call(expression); } } } }); this.hooks.evaluate.for("CallExpression").tap("Parser", expr => { - if(expr.callee.type !== "MemberExpression") return; - if(expr.callee.property.type !== (expr.callee.computed ? "Literal" : "Identifier")) return; + if (expr.callee.type !== "MemberExpression") return; + if ( + expr.callee.property.type !== + (expr.callee.computed ? "Literal" : "Identifier") + ) + return; const param = this.evaluateExpression(expr.callee.object); - if(!param) return; + if (!param) return; const property = expr.callee.property.name || expr.callee.property.value; const hook = this.hooks.evaluateCallExpressionMember.get(property); - if(hook !== undefined) { + if (hook !== undefined) { return hook.call(expr, param); } }); - this.hooks.evaluateCallExpressionMember.for("replace").tap("Parser", (expr, param) => { - if(!param.isString()) return; - if(expr.arguments.length !== 2) return; - let arg1 = this.evaluateExpression(expr.arguments[0]); - let arg2 = this.evaluateExpression(expr.arguments[1]); - if(!arg1.isString() && !arg1.isRegExp()) return; - arg1 = arg1.regExp || arg1.string; - if(!arg2.isString()) return; - arg2 = arg2.string; - return new BasicEvaluatedExpression().setString(param.string.replace(arg1, arg2)).setRange(expr.range); - }); + this.hooks.evaluateCallExpressionMember + .for("replace") + .tap("Parser", (expr, param) => { + if (!param.isString()) return; + if (expr.arguments.length !== 2) return; + let arg1 = this.evaluateExpression(expr.arguments[0]); + let arg2 = this.evaluateExpression(expr.arguments[1]); + if (!arg1.isString() && !arg1.isRegExp()) return; + arg1 = arg1.regExp || arg1.string; + if (!arg2.isString()) return; + arg2 = arg2.string; + return new BasicEvaluatedExpression() + .setString(param.string.replace(arg1, arg2)) + .setRange(expr.range); + }); ["substr", "substring"].forEach(fn => { - this.hooks.evaluateCallExpressionMember.for(fn).tap("Parser", (expr, param) => { - if(!param.isString()) return; - let arg1; - let result, str = param.string; - switch(expr.arguments.length) { - case 1: - arg1 = this.evaluateExpression(expr.arguments[0]); - if(!arg1.isNumber()) return; - result = str[fn](arg1.number); - break; - case 2: - { + this.hooks.evaluateCallExpressionMember + .for(fn) + .tap("Parser", (expr, param) => { + if (!param.isString()) return; + let arg1; + let result, + str = param.string; + switch (expr.arguments.length) { + case 1: + arg1 = this.evaluateExpression(expr.arguments[0]); + if (!arg1.isNumber()) return; + result = str[fn](arg1.number); + break; + case 2: { arg1 = this.evaluateExpression(expr.arguments[0]); const arg2 = this.evaluateExpression(expr.arguments[1]); - if(!arg1.isNumber()) return; - if(!arg2.isNumber()) return; + if (!arg1.isNumber()) return; + if (!arg2.isNumber()) return; result = str[fn](arg1.number, arg2.number); break; } - default: - return; - } - return new BasicEvaluatedExpression().setString(result).setRange(expr.range); - }); + default: + return; + } + return new BasicEvaluatedExpression() + .setString(result) + .setRange(expr.range); + }); }); /** @@ -494,16 +588,24 @@ class Parser extends Tapable { const getSimplifiedTemplateResult = (kind, quasis, expressions) => { const parts = []; - for(let i = 0; i < quasis.length; i++) { - parts.push(new BasicEvaluatedExpression().setString(quasis[i].value[kind]).setRange(quasis[i].range)); + for (let i = 0; i < quasis.length; i++) { + parts.push( + new BasicEvaluatedExpression() + .setString(quasis[i].value[kind]) + .setRange(quasis[i].range) + ); - if(i > 0) { + if (i > 0) { const prevExpr = parts[parts.length - 2], lastExpr = parts[parts.length - 1]; const expr = this.evaluateExpression(expressions[i - 1]); - if(!(expr.isString() || expr.isNumber())) continue; + if (!(expr.isString() || expr.isNumber())) continue; - prevExpr.setString(prevExpr.string + (expr.isString() ? expr.string : expr.number) + lastExpr.string); + prevExpr.setString( + prevExpr.string + + (expr.isString() ? expr.string : expr.number) + + lastExpr.string + ); prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]); parts.pop(); } @@ -512,79 +614,111 @@ class Parser extends Tapable { }; this.hooks.evaluate.for("TemplateLiteral").tap("Parser", node => { - const parts = getSimplifiedTemplateResult.call(this, "cooked", node.quasis, node.expressions); - if(parts.length === 1) { + const parts = getSimplifiedTemplateResult.call( + this, + "cooked", + node.quasis, + node.expressions + ); + if (parts.length === 1) { return parts[0].setRange(node.range); } - return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range); + return new BasicEvaluatedExpression() + .setTemplateString(parts) + .setRange(node.range); }); this.hooks.evaluate.for("TaggedTemplateExpression").tap("Parser", node => { - if(this.evaluateExpression(node.tag).identifier !== "String.raw") return; - const parts = getSimplifiedTemplateResult.call(this, "raw", node.quasi.quasis, node.quasi.expressions); - return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range); + if (this.evaluateExpression(node.tag).identifier !== "String.raw") return; + const parts = getSimplifiedTemplateResult.call( + this, + "raw", + node.quasi.quasis, + node.quasi.expressions + ); + return new BasicEvaluatedExpression() + .setTemplateString(parts) + .setRange(node.range); }); - this.hooks.evaluateCallExpressionMember.for("concat").tap("Parser", (expr, param) => { - if(!param.isString() && !param.isWrapped()) return; + this.hooks.evaluateCallExpressionMember + .for("concat") + .tap("Parser", (expr, param) => { + if (!param.isString() && !param.isWrapped()) return; - let stringSuffix = null; - let hasUnknownParams = false; - for(let i = expr.arguments.length - 1; i >= 0; i--) { - const argExpr = this.evaluateExpression(expr.arguments[i]); - if(!argExpr.isString() && !argExpr.isNumber()) { - hasUnknownParams = true; - break; + let stringSuffix = null; + let hasUnknownParams = false; + for (let i = expr.arguments.length - 1; i >= 0; i--) { + const argExpr = this.evaluateExpression(expr.arguments[i]); + if (!argExpr.isString() && !argExpr.isNumber()) { + hasUnknownParams = true; + break; + } + + const value = argExpr.isString() + ? argExpr.string + : "" + argExpr.number; + + const newString = value + (stringSuffix ? stringSuffix.string : ""); + const newRange = [ + argExpr.range[0], + (stringSuffix || argExpr).range[1] + ]; + stringSuffix = new BasicEvaluatedExpression() + .setString(newString) + .setRange(newRange); } - const value = argExpr.isString() ? argExpr.string : "" + argExpr.number; - - const newString = value + (stringSuffix ? stringSuffix.string : ""); - const newRange = [argExpr.range[0], (stringSuffix || argExpr).range[1]]; - stringSuffix = new BasicEvaluatedExpression().setString(newString).setRange(newRange); - } - - if(hasUnknownParams) { - const prefix = param.isString() ? param : param.prefix; - return new BasicEvaluatedExpression().setWrapped(prefix, stringSuffix).setRange(expr.range); - } else if(param.isWrapped()) { - const postfix = stringSuffix || param.postfix; - return new BasicEvaluatedExpression().setWrapped(param.prefix, postfix).setRange(expr.range); - } else { - const newString = param.string + (stringSuffix ? stringSuffix.string : ""); - return new BasicEvaluatedExpression().setString(newString).setRange(expr.range); - } - }); - this.hooks.evaluateCallExpressionMember.for("split").tap("Parser", (expr, param) => { - if(!param.isString()) return; - if(expr.arguments.length !== 1) return; - let result; - const arg = this.evaluateExpression(expr.arguments[0]); - if(arg.isString()) { - result = param.string.split(arg.string); - } else if(arg.isRegExp()) { - result = param.string.split(arg.regExp); - } else return; - return new BasicEvaluatedExpression().setArray(result).setRange(expr.range); - }); + if (hasUnknownParams) { + const prefix = param.isString() ? param : param.prefix; + return new BasicEvaluatedExpression() + .setWrapped(prefix, stringSuffix) + .setRange(expr.range); + } else if (param.isWrapped()) { + const postfix = stringSuffix || param.postfix; + return new BasicEvaluatedExpression() + .setWrapped(param.prefix, postfix) + .setRange(expr.range); + } else { + const newString = + param.string + (stringSuffix ? stringSuffix.string : ""); + return new BasicEvaluatedExpression() + .setString(newString) + .setRange(expr.range); + } + }); + this.hooks.evaluateCallExpressionMember + .for("split") + .tap("Parser", (expr, param) => { + if (!param.isString()) return; + if (expr.arguments.length !== 1) return; + let result; + const arg = this.evaluateExpression(expr.arguments[0]); + if (arg.isString()) { + result = param.string.split(arg.string); + } else if (arg.isRegExp()) { + result = param.string.split(arg.regExp); + } else return; + return new BasicEvaluatedExpression() + .setArray(result) + .setRange(expr.range); + }); this.hooks.evaluate.for("ConditionalExpression").tap("Parser", expr => { const condition = this.evaluateExpression(expr.test); const conditionValue = condition.asBool(); let res; - if(conditionValue === undefined) { + if (conditionValue === undefined) { const consequent = this.evaluateExpression(expr.consequent); const alternate = this.evaluateExpression(expr.alternate); - if(!consequent || !alternate) return; + if (!consequent || !alternate) return; res = new BasicEvaluatedExpression(); - if(consequent.isConditional()) - res.setOptions(consequent.options); - else - res.setOptions([consequent]); - if(alternate.isConditional()) - res.addOptions(alternate.options); - else - res.addOptions([alternate]); + if (consequent.isConditional()) res.setOptions(consequent.options); + else res.setOptions([consequent]); + if (alternate.isConditional()) res.addOptions(alternate.options); + else res.addOptions([alternate]); } else { - res = this.evaluateExpression(conditionValue ? expr.consequent : expr.alternate); + res = this.evaluateExpression( + conditionValue ? expr.consequent : expr.alternate + ); } res.setRange(expr.range); return res; @@ -593,26 +727,27 @@ class Parser extends Tapable { const items = expr.elements.map(element => { return element !== null && this.evaluateExpression(element); }); - if(!items.every(Boolean)) return; - return new BasicEvaluatedExpression().setItems(items).setRange(expr.range); + if (!items.every(Boolean)) return; + return new BasicEvaluatedExpression() + .setItems(items) + .setRange(expr.range); }); } getRenameIdentifier(expr) { const result = this.evaluateExpression(expr); - if(!result) return; - if(result.isIdentifier()) return result.identifier; + if (!result) return; + if (result.isIdentifier()) return result.identifier; return; } walkClass(classy) { - if(classy.superClass) - this.walkExpression(classy.superClass); - if(classy.body && classy.body.type === "ClassBody") { + if (classy.superClass) this.walkExpression(classy.superClass); + if (classy.body && classy.body.type === "ClassBody") { const wasTopLevel = this.scope.topLevelScope; this.scope.topLevelScope = false; - for(const methodDefinition of classy.body.body) { - if(methodDefinition.type === "MethodDefinition") + for (const methodDefinition of classy.body.body) { + if (methodDefinition.type === "MethodDefinition") this.walkMethodDefinition(methodDefinition); } this.scope.topLevelScope = wasTopLevel; @@ -620,15 +755,14 @@ class Parser extends Tapable { } walkMethodDefinition(methodDefinition) { - if(methodDefinition.computed && methodDefinition.key) + if (methodDefinition.computed && methodDefinition.key) this.walkExpression(methodDefinition.key); - if(methodDefinition.value) - this.walkExpression(methodDefinition.value); + if (methodDefinition.value) this.walkExpression(methodDefinition.value); } // Prewalking iterates the scope for variable declarations prewalkStatements(statements) { - for(let index = 0, len = statements.length; index < len; index++) { + for (let index = 0, len = statements.length; index < len; index++) { const statement = statements[index]; this.prewalkStatement(statement); } @@ -636,14 +770,14 @@ class Parser extends Tapable { // Walking iterates the statements and expressions and processes them walkStatements(statements) { - for(let index = 0, len = statements.length; index < len; index++) { + for (let index = 0, len = statements.length; index < len; index++) { const statement = statements[index]; this.walkStatement(statement); } } prewalkStatement(statement) { - switch(statement.type) { + switch (statement.type) { case "BlockStatement": this.prewalkBlockStatement(statement); break; @@ -702,8 +836,8 @@ class Parser extends Tapable { } walkStatement(statement) { - if(this.hooks.statement.call(statement) !== undefined) return; - switch(statement.type) { + if (this.hooks.statement.call(statement) !== undefined) return; + switch (statement.type) { case "BlockStatement": this.walkBlockStatement(statement); break; @@ -779,22 +913,18 @@ class Parser extends Tapable { prewalkIfStatement(statement) { this.prewalkStatement(statement.consequent); - if(statement.alternate) - this.prewalkStatement(statement.alternate); + if (statement.alternate) this.prewalkStatement(statement.alternate); } walkIfStatement(statement) { const result = this.hooks.statementIf.call(statement); - if(result === undefined) { + if (result === undefined) { this.walkExpression(statement.test); this.walkStatement(statement.consequent); - if(statement.alternate) - this.walkStatement(statement.alternate); + if (statement.alternate) this.walkStatement(statement.alternate); } else { - if(result) - this.walkStatement(statement.consequent); - else if(statement.alternate) - this.walkStatement(statement.alternate); + if (result) this.walkStatement(statement.consequent); + else if (statement.alternate) this.walkStatement(statement.alternate); } } @@ -804,10 +934,9 @@ class Parser extends Tapable { walkLabeledStatement(statement) { const hook = this.hooks.label.get(statement.label.name); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(statement); - if(result === true) - return; + if (result === true) return; } this.walkStatement(statement.body); } @@ -831,8 +960,7 @@ class Parser extends Tapable { } walkTerminatingStatement(statement) { - if(statement.argument) - this.walkExpression(statement.argument); + if (statement.argument) this.walkExpression(statement.argument); } walkReturnStatement(statement) { @@ -848,17 +976,15 @@ class Parser extends Tapable { } walkTryStatement(statement) { - if(this.scope.inTry) { + if (this.scope.inTry) { this.walkStatement(statement.block); } else { this.scope.inTry = true; this.walkStatement(statement.block); this.scope.inTry = false; } - if(statement.handler) - this.walkCatchClause(statement.handler); - if(statement.finalizer) - this.walkStatement(statement.finalizer); + if (statement.handler) this.walkCatchClause(statement.handler); + if (statement.finalizer) this.walkStatement(statement.finalizer); } prewalkWhileStatement(statement) { @@ -880,71 +1006,65 @@ class Parser extends Tapable { } prewalkForStatement(statement) { - if(statement.init) { - if(statement.init.type === "VariableDeclaration") + if (statement.init) { + if (statement.init.type === "VariableDeclaration") this.prewalkStatement(statement.init); } this.prewalkStatement(statement.body); } walkForStatement(statement) { - if(statement.init) { - if(statement.init.type === "VariableDeclaration") + if (statement.init) { + if (statement.init.type === "VariableDeclaration") this.walkStatement(statement.init); - else - this.walkExpression(statement.init); + else this.walkExpression(statement.init); } - if(statement.test) - this.walkExpression(statement.test); - if(statement.update) - this.walkExpression(statement.update); + if (statement.test) this.walkExpression(statement.test); + if (statement.update) this.walkExpression(statement.update); this.walkStatement(statement.body); } prewalkForInStatement(statement) { - if(statement.left.type === "VariableDeclaration") + if (statement.left.type === "VariableDeclaration") this.prewalkVariableDeclaration(statement.left); this.prewalkStatement(statement.body); } walkForInStatement(statement) { - if(statement.left.type === "VariableDeclaration") + if (statement.left.type === "VariableDeclaration") this.walkVariableDeclaration(statement.left); - else - this.walkPattern(statement.left); + else this.walkPattern(statement.left); this.walkExpression(statement.right); this.walkStatement(statement.body); } prewalkForOfStatement(statement) { - if(statement.left.type === "VariableDeclaration") + if (statement.left.type === "VariableDeclaration") this.prewalkVariableDeclaration(statement.left); this.prewalkStatement(statement.body); } walkForOfStatement(statement) { - if(statement.left.type === "VariableDeclaration") + if (statement.left.type === "VariableDeclaration") this.walkVariableDeclaration(statement.left); - else - this.walkPattern(statement.left); + else this.walkPattern(statement.left); this.walkExpression(statement.right); this.walkStatement(statement.body); } // Declarations prewalkFunctionDeclaration(statement) { - if(statement.id) { + if (statement.id) { this.scope.renames.set(statement.id.name, null); this.scope.definitions.add(statement.id.name); } } walkFunctionDeclaration(statement) { - for(const param of statement.params) - this.walkPattern(param); + for (const param of statement.params) this.walkPattern(param); this.inScope(statement.params, () => { this.scope.topLevelScope = false; - if(statement.body.type === "BlockStatement") { + if (statement.body.type === "BlockStatement") { this.detectStrictMode(statement.body.body); this.prewalkStatement(statement.body); this.walkStatement(statement.body); @@ -957,16 +1077,21 @@ class Parser extends Tapable { prewalkImportDeclaration(statement) { const source = statement.source.value; this.hooks.import.call(statement, source); - for(const specifier of statement.specifiers) { + for (const specifier of statement.specifiers) { const name = specifier.local.name; this.scope.renames.set(name, null); this.scope.definitions.add(name); - switch(specifier.type) { + switch (specifier.type) { case "ImportDefaultSpecifier": this.hooks.importSpecifier.call(statement, source, "default", name); break; case "ImportSpecifier": - this.hooks.importSpecifier.call(statement, source, specifier.imported.name, name); + this.hooks.importSpecifier.call( + statement, + source, + specifier.imported.name, + name + ); break; case "ImportNamespaceSpecifier": this.hooks.importSpecifier.call(statement, source, null, name); @@ -977,59 +1102,75 @@ class Parser extends Tapable { prewalkExportNamedDeclaration(statement) { let source; - if(statement.source) { + if (statement.source) { source = statement.source.value; this.hooks.exportImport.call(statement, source); } else { this.hooks.export.call(statement); } - if(statement.declaration) { - if(!this.hooks.exportDeclaration.call(statement, statement.declaration)) { + if (statement.declaration) { + if ( + !this.hooks.exportDeclaration.call(statement, statement.declaration) + ) { const originalDefinitions = this.scope.definitions; const tracker = new TrackingSet(this.scope.definitions); this.scope.definitions = tracker; this.prewalkStatement(statement.declaration); const newDefs = Array.from(tracker.getAddedItems()); this.scope.definitions = originalDefinitions; - for(let index = newDefs.length - 1; index >= 0; index--) { + for (let index = newDefs.length - 1; index >= 0; index--) { const def = newDefs[index]; this.hooks.exportSpecifier.call(statement, def, def, index); } } } - if(statement.specifiers) { - for(let specifierIndex = 0; specifierIndex < statement.specifiers.length; specifierIndex++) { + if (statement.specifiers) { + for ( + let specifierIndex = 0; + specifierIndex < statement.specifiers.length; + specifierIndex++ + ) { const specifier = statement.specifiers[specifierIndex]; - switch(specifier.type) { - case "ExportSpecifier": - { - const name = specifier.exported.name; - if(source) - this.hooks.exportImportSpecifier.call(statement, source, specifier.local.name, name, specifierIndex); - else - this.hooks.exportSpecifier.call(statement, specifier.local.name, name, specifierIndex); - break; - } + switch (specifier.type) { + case "ExportSpecifier": { + const name = specifier.exported.name; + if (source) + this.hooks.exportImportSpecifier.call( + statement, + source, + specifier.local.name, + name, + specifierIndex + ); + else + this.hooks.exportSpecifier.call( + statement, + specifier.local.name, + name, + specifierIndex + ); + break; + } } } } } walkExportNamedDeclaration(statement) { - if(statement.declaration) { + if (statement.declaration) { this.walkStatement(statement.declaration); } } prewalkExportDefaultDeclaration(statement) { - if(statement.declaration.id) { + if (statement.declaration.id) { const originalDefinitions = this.scope.definitions; const tracker = new TrackingSet(this.scope.definitions); this.scope.definitions = tracker; this.prewalkStatement(statement.declaration); const newDefs = Array.from(tracker.getAddedItems()); this.scope.definitions = originalDefinitions; - for(let index = 0, len = newDefs.length; index < len; index++) { + for (let index = 0, len = newDefs.length; index < len; index++) { const def = newDefs[index]; this.hooks.exportSpecifier.call(statement, def, "default"); } @@ -1038,23 +1179,29 @@ class Parser extends Tapable { walkExportDefaultDeclaration(statement) { this.hooks.export.call(statement); - if(statement.declaration.id) { - if(!this.hooks.exportDeclaration.call(statement, statement.declaration)) { + if (statement.declaration.id) { + if ( + !this.hooks.exportDeclaration.call(statement, statement.declaration) + ) { this.walkStatement(statement.declaration); } } else { // Acorn parses `export default function() {}` as `FunctionDeclaration` and // `export default class {}` as `ClassDeclaration`, both with `id = null`. // These nodes must be treated as expressions. - if(statement.declaration.type === "FunctionDeclaration") { + if (statement.declaration.type === "FunctionDeclaration") { this.walkFunctionDeclaration(statement.declaration); - } else if(statement.declaration.type === "ClassDeclaration") { + } else if (statement.declaration.type === "ClassDeclaration") { this.walkClassDeclaration(statement.declaration); } else { this.walkExpression(statement.declaration); } - if(!this.hooks.exportExpression.call(statement, statement.declaration)) { - this.hooks.exportSpecifier.call(statement, statement.declaration, "default"); + if (!this.hooks.exportExpression.call(statement, statement.declaration)) { + this.hooks.exportSpecifier.call( + statement, + statement.declaration, + "default" + ); } } } @@ -1066,58 +1213,62 @@ class Parser extends Tapable { } prewalkVariableDeclaration(statement) { - const hookMap = statement.kind === "const" ? this.hooks.varDeclarationConst : - statement.kind === "let" ? this.hooks.varDeclarationLet : - this.hooks.varDeclarationVar; - for(const declarator of statement.declarations) { - switch(declarator.type) { - case "VariableDeclarator": - { - this.enterPattern(declarator.id, (name, decl) => { - let hook = hookMap.get(name); - if(hook === undefined || !hook.call(decl)) { - hook = this.hooks.varDeclaration.get(name); - if(hook === undefined || !hook.call(decl)) { - this.scope.renames.set(name, null); - this.scope.definitions.add(name); - } + const hookMap = + statement.kind === "const" + ? this.hooks.varDeclarationConst + : statement.kind === "let" + ? this.hooks.varDeclarationLet + : this.hooks.varDeclarationVar; + for (const declarator of statement.declarations) { + switch (declarator.type) { + case "VariableDeclarator": { + this.enterPattern(declarator.id, (name, decl) => { + let hook = hookMap.get(name); + if (hook === undefined || !hook.call(decl)) { + hook = this.hooks.varDeclaration.get(name); + if (hook === undefined || !hook.call(decl)) { + this.scope.renames.set(name, null); + this.scope.definitions.add(name); } - }); - break; - } + } + }); + break; + } } } } walkVariableDeclaration(statement) { - for(const declarator of statement.declarations) { - switch(declarator.type) { - case "VariableDeclarator": - { - const renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init); - if(renameIdentifier && declarator.id.type === "Identifier") { - const hook = this.hooks.canRename.get(renameIdentifier); - if(hook !== undefined && hook.call(declarator.init)) { - // renaming with "var a = b;" - const hook = this.hooks.rename.get(renameIdentifier); - if(hook === undefined || !hook.call(declarator.init)) { - this.scope.renames.set(declarator.id.name, this.scope.renames.get(renameIdentifier) || renameIdentifier); - this.scope.definitions.delete(declarator.id.name); - } - break; + for (const declarator of statement.declarations) { + switch (declarator.type) { + case "VariableDeclarator": { + const renameIdentifier = + declarator.init && this.getRenameIdentifier(declarator.init); + if (renameIdentifier && declarator.id.type === "Identifier") { + const hook = this.hooks.canRename.get(renameIdentifier); + if (hook !== undefined && hook.call(declarator.init)) { + // renaming with "var a = b;" + const hook = this.hooks.rename.get(renameIdentifier); + if (hook === undefined || !hook.call(declarator.init)) { + this.scope.renames.set( + declarator.id.name, + this.scope.renames.get(renameIdentifier) || renameIdentifier + ); + this.scope.definitions.delete(declarator.id.name); } + break; } - this.walkPattern(declarator.id); - if(declarator.init) - this.walkExpression(declarator.init); - break; } + this.walkPattern(declarator.id); + if (declarator.init) this.walkExpression(declarator.init); + break; + } } } } prewalkClassDeclaration(statement) { - if(statement.id) { + if (statement.id) { this.scope.renames.set(statement.id.name, null); this.scope.definitions.add(statement.id.name); } @@ -1128,17 +1279,17 @@ class Parser extends Tapable { } prewalkSwitchCases(switchCases) { - for(let index = 0, len = switchCases.length; index < len; index++) { + for (let index = 0, len = switchCases.length; index < len; index++) { const switchCase = switchCases[index]; this.prewalkStatements(switchCase.consequent); } } walkSwitchCases(switchCases) { - for(let index = 0, len = switchCases.length; index < len; index++) { + for (let index = 0, len = switchCases.length; index < len; index++) { const switchCase = switchCases[index]; - if(switchCase.test) { + if (switchCase.test) { this.walkExpression(switchCase.test); } this.walkStatements(switchCase.consequent); @@ -1153,7 +1304,7 @@ class Parser extends Tapable { } walkPattern(pattern) { - switch(pattern.type) { + switch (pattern.type) { case "ArrayPattern": this.walkArrayPattern(pattern); break; @@ -1178,22 +1329,19 @@ class Parser extends Tapable { } walkObjectPattern(pattern) { - for(let i = 0, len = pattern.properties.length; i < len; i++) { + for (let i = 0, len = pattern.properties.length; i < len; i++) { const prop = pattern.properties[i]; - if(prop) { - if(prop.computed) - this.walkExpression(prop.key); - if(prop.value) - this.walkPattern(prop.value); + if (prop) { + if (prop.computed) this.walkExpression(prop.key); + if (prop.value) this.walkPattern(prop.value); } } } walkArrayPattern(pattern) { - for(let i = 0, len = pattern.elements.length; i < len; i++) { + for (let i = 0, len = pattern.elements.length; i < len; i++) { const element = pattern.elements[i]; - if(element) - this.walkPattern(element); + if (element) this.walkPattern(element); } } @@ -1202,15 +1350,18 @@ class Parser extends Tapable { } walkExpressions(expressions) { - for(let expressionsIndex = 0, len = expressions.length; expressionsIndex < len; expressionsIndex++) { + for ( + let expressionsIndex = 0, len = expressions.length; + expressionsIndex < len; + expressionsIndex++ + ) { const expression = expressions[expressionsIndex]; - if(expression) - this.walkExpression(expression); + if (expression) this.walkExpression(expression); } } walkExpression(expression) { - switch(expression.type) { + switch (expression.type) { case "ArrayExpression": this.walkArrayExpression(expression); break; @@ -1285,38 +1436,36 @@ class Parser extends Tapable { } walkArrayExpression(expression) { - if(expression.elements) - this.walkExpressions(expression.elements); + if (expression.elements) this.walkExpressions(expression.elements); } walkSpreadElement(expression) { - if(expression.argument) - this.walkExpression(expression.argument); + if (expression.argument) this.walkExpression(expression.argument); } walkObjectExpression(expression) { - for(let propIndex = 0, len = expression.properties.length; propIndex < len; propIndex++) { + for ( + let propIndex = 0, len = expression.properties.length; + propIndex < len; + propIndex++ + ) { const prop = expression.properties[propIndex]; - if(prop.type === "SpreadElement") { + if (prop.type === "SpreadElement") { this.walkExpression(prop.argument); continue; } - if(prop.computed) - this.walkExpression(prop.key); - if(prop.shorthand) - this.scope.inShorthand = true; + if (prop.computed) this.walkExpression(prop.key); + if (prop.shorthand) this.scope.inShorthand = true; this.walkExpression(prop.value); - if(prop.shorthand) - this.scope.inShorthand = false; + if (prop.shorthand) this.scope.inShorthand = false; } } walkFunctionExpression(expression) { - for(const param of expression.params) - this.walkPattern(param); + for (const param of expression.params) this.walkPattern(param); this.inScope(expression.params, () => { this.scope.topLevelScope = false; - if(expression.body.type === "BlockStatement") { + if (expression.body.type === "BlockStatement") { this.detectStrictMode(expression.body.body); this.prewalkStatement(expression.body); this.walkStatement(expression.body); @@ -1327,10 +1476,9 @@ class Parser extends Tapable { } walkArrowFunctionExpression(expression) { - for(const param of expression.params) - this.walkPattern(param); + for (const param of expression.params) this.walkPattern(param); this.inScope(expression.params, () => { - if(expression.body.type === "BlockStatement") { + if (expression.body.type === "BlockStatement") { this.detectStrictMode(expression.body.body); this.prewalkStatement(expression.body); this.walkStatement(expression.body); @@ -1341,8 +1489,7 @@ class Parser extends Tapable { } walkSequenceExpression(expression) { - if(expression.expressions) - this.walkExpressions(expression.expressions); + if (expression.expressions) this.walkExpressions(expression.expressions); } walkUpdateExpression(expression) { @@ -1350,14 +1497,13 @@ class Parser extends Tapable { } walkUnaryExpression(expression) { - if(expression.operator === "typeof") { + if (expression.operator === "typeof") { const exprName = this.getNameForExpression(expression.argument); - if(exprName && exprName.free) { + if (exprName && exprName.free) { const hook = this.hooks.typeof.get(exprName.name); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(expression); - if(result === true) - return; + if (result === true) return; } } } @@ -1379,26 +1525,26 @@ class Parser extends Tapable { walkAssignmentExpression(expression) { const renameIdentifier = this.getRenameIdentifier(expression.right); - if(expression.left.type === "Identifier" && renameIdentifier) { + if (expression.left.type === "Identifier" && renameIdentifier) { const hook = this.hooks.canRename.get(renameIdentifier); - if(hook !== undefined && hook.call(expression.right)) { + if (hook !== undefined && hook.call(expression.right)) { // renaming "a = b;" const hook = this.hooks.rename.get(renameIdentifier); - if(hook === undefined || !hook.call(expression.right)) { + if (hook === undefined || !hook.call(expression.right)) { this.scope.renames.set(expression.left.name, renameIdentifier); this.scope.definitions.delete(expression.left.name); } return; } } - if(expression.left.type === "Identifier") { + if (expression.left.type === "Identifier") { const assignedHook = this.hooks.assigned.get(expression.left.name); - if(assignedHook === undefined || !assignedHook.call(expression)) { + if (assignedHook === undefined || !assignedHook.call(expression)) { this.walkExpression(expression.right); } this.scope.renames.set(expression.left.name, null); const assignHook = this.hooks.assign.get(expression.left.name); - if(assignHook === undefined || !assignHook.call(expression)) { + if (assignHook === undefined || !assignHook.call(expression)) { this.walkExpression(expression.left); } return; @@ -1412,50 +1558,43 @@ class Parser extends Tapable { walkConditionalExpression(expression) { const result = this.hooks.expressionConditionalOperator.call(expression); - if(result === undefined) { + if (result === undefined) { this.walkExpression(expression.test); this.walkExpression(expression.consequent); - if(expression.alternate) - this.walkExpression(expression.alternate); + if (expression.alternate) this.walkExpression(expression.alternate); } else { - if(result) - this.walkExpression(expression.consequent); - else if(expression.alternate) - this.walkExpression(expression.alternate); + if (result) this.walkExpression(expression.consequent); + else if (expression.alternate) this.walkExpression(expression.alternate); } } walkNewExpression(expression) { const callee = this.evaluateExpression(expression.callee); - if(callee.isIdentifier()) { + if (callee.isIdentifier()) { const hook = this.hooks.new.get(callee.identifier); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(expression); - if(result === true) { + if (result === true) { return; } } } this.walkExpression(expression.callee); - if(expression.arguments) - this.walkExpressions(expression.arguments); + if (expression.arguments) this.walkExpressions(expression.arguments); } walkYieldExpression(expression) { - if(expression.argument) - this.walkExpression(expression.argument); + if (expression.argument) this.walkExpression(expression.argument); } walkTemplateLiteral(expression) { - if(expression.expressions) - this.walkExpressions(expression.expressions); + if (expression.expressions) this.walkExpressions(expression.expressions); } walkTaggedTemplateExpression(expression) { - if(expression.tag) - this.walkExpression(expression.tag); - if(expression.quasi && expression.quasi.expressions) + if (expression.tag) this.walkExpression(expression.tag); + if (expression.quasi && expression.quasi.expressions) this.walkExpressions(expression.quasi.expressions); } @@ -1469,118 +1608,122 @@ class Parser extends Tapable { const walkIIFE = (functionExpression, options, currentThis) => { const renameArgOrThis = argOrThis => { const renameIdentifier = this.getRenameIdentifier(argOrThis); - if(renameIdentifier) { + if (renameIdentifier) { const hook = this.hooks.canRename.get(renameIdentifier); - if(hook !== undefined && hook.call(argOrThis)) { + if (hook !== undefined && hook.call(argOrThis)) { const hook = this.hooks.rename.get(renameIdentifier); - if(hook === undefined || !hook.call(argOrThis)) + if (hook === undefined || !hook.call(argOrThis)) return renameIdentifier; } } this.walkExpression(argOrThis); }; const params = functionExpression.params; - const renameThis = currentThis ? renameArgOrThis.call(this, currentThis) : null; + const renameThis = currentThis + ? renameArgOrThis.call(this, currentThis) + : null; const args = options.map(renameArgOrThis); this.inScope(params.filter((identifier, idx) => !args[idx]), () => { - if(renameThis) { + if (renameThis) { this.scope.renames.set("this", renameThis); } - for(let i = 0; i < args.length; i++) { + for (let i = 0; i < args.length; i++) { const param = args[i]; - if(!param) continue; - if(!params[i] || params[i].type !== "Identifier") continue; + if (!param) continue; + if (!params[i] || params[i].type !== "Identifier") continue; this.scope.renames.set(params[i].name, param); } - if(functionExpression.body.type === "BlockStatement") { + if (functionExpression.body.type === "BlockStatement") { this.prewalkStatement(functionExpression.body); this.walkStatement(functionExpression.body); - } else - this.walkExpression(functionExpression.body); + } else this.walkExpression(functionExpression.body); }); }; - if(expression.callee.type === "MemberExpression" && + if ( + expression.callee.type === "MemberExpression" && expression.callee.object.type === "FunctionExpression" && !expression.callee.computed && - (expression.callee.property.name === "call" || expression.callee.property.name === "bind") && + (expression.callee.property.name === "call" || + expression.callee.property.name === "bind") && expression.arguments && expression.arguments.length > 0 ) { // (function(...) { }.call/bind(?, ...)) - walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1), expression.arguments[0]); - } else if(expression.callee.type === "FunctionExpression" && expression.arguments) { + walkIIFE.call( + this, + expression.callee.object, + expression.arguments.slice(1), + expression.arguments[0] + ); + } else if ( + expression.callee.type === "FunctionExpression" && + expression.arguments + ) { // (function(...) { }(...)) walkIIFE.call(this, expression.callee, expression.arguments); - } else if(expression.callee.type === "Import") { + } else if (expression.callee.type === "Import") { result = this.hooks.importCall.call(expression); - if(result === true) - return; + if (result === true) return; - if(expression.arguments) - this.walkExpressions(expression.arguments); + if (expression.arguments) this.walkExpressions(expression.arguments); } else { - const callee = this.evaluateExpression(expression.callee); - if(callee.isIdentifier()) { + if (callee.isIdentifier()) { const callHook = this.hooks.call.get(callee.identifier); - if(callHook !== undefined) { + if (callHook !== undefined) { result = callHook.call(expression); - if(result === true) - return; + if (result === true) return; } let identifier = callee.identifier.replace(/\.[^.]+$/, ""); - if(identifier !== callee.identifier) { + if (identifier !== callee.identifier) { const callAnyHook = this.hooks.callAnyMember.get(identifier); - if(callAnyHook !== undefined) { + if (callAnyHook !== undefined) { result = callAnyHook.call(expression); - if(result === true) - return; + if (result === true) return; } } } - if(expression.callee) - this.walkExpression(expression.callee); - if(expression.arguments) - this.walkExpressions(expression.arguments); + if (expression.callee) this.walkExpression(expression.callee); + if (expression.arguments) this.walkExpressions(expression.arguments); } } walkMemberExpression(expression) { const exprName = this.getNameForExpression(expression); - if(exprName && exprName.free) { + if (exprName && exprName.free) { const expressionHook = this.hooks.expression.get(exprName.name); - if(expressionHook !== undefined) { + if (expressionHook !== undefined) { const result = expressionHook.call(expression); - if(result === true) - return; + if (result === true) return; } - const expressionAnyMemberHook = this.hooks.expressionAnyMember.get(exprName.nameGeneral); - if(expressionAnyMemberHook !== undefined) { + const expressionAnyMemberHook = this.hooks.expressionAnyMember.get( + exprName.nameGeneral + ); + if (expressionAnyMemberHook !== undefined) { const result = expressionAnyMemberHook.call(expression); - if(result === true) - return; + if (result === true) return; } } this.walkExpression(expression.object); - if(expression.computed === true) - this.walkExpression(expression.property); + if (expression.computed === true) this.walkExpression(expression.property); } walkThisExpression(expression) { const expressionHook = this.hooks.expression.get("this"); - if(expressionHook !== undefined) { + if (expressionHook !== undefined) { expressionHook.call(expression); } } walkIdentifier(expression) { - if(!this.scope.definitions.has(expression.name)) { - const hook = this.hooks.expression.get(this.scope.renames.get(expression.name) || expression.name); - if(hook !== undefined) { + if (!this.scope.definitions.has(expression.name)) { + const hook = this.hooks.expression.get( + this.scope.renames.get(expression.name) || expression.name + ); + if (hook !== undefined) { const result = hook.call(expression); - if(result === true) - return; + if (result === true) return; } } } @@ -1598,15 +1741,19 @@ class Parser extends Tapable { this.scope.renames.set("this", null); - for(let paramIndex = 0, len = params.length; paramIndex < len; paramIndex++) { + for ( + let paramIndex = 0, len = params.length; + paramIndex < len; + paramIndex++ + ) { const param = params[paramIndex]; - if(typeof param !== "string") { + if (typeof param !== "string") { this.enterPattern(param, param => { this.scope.renames.set(param, null); this.scope.definitions.add(param); }); - } else if(param) { + } else if (param) { this.scope.renames.set(param, null); this.scope.definitions.add(param); } @@ -1617,18 +1764,19 @@ class Parser extends Tapable { } detectStrictMode(statements) { - const isStrict = statements.length >= 1 && + const isStrict = + statements.length >= 1 && statements[0].type === "ExpressionStatement" && statements[0].expression.type === "Literal" && statements[0].expression.value === "use strict"; - if(isStrict) { + if (isStrict) { this.scope.isStrict = true; } } enterPattern(pattern, onIdent) { - if(!pattern) return; - switch(pattern.type) { + if (!pattern) return; + switch (pattern.type) { case "ArrayPattern": this.enterArrayPattern(pattern, onIdent); break; @@ -1652,14 +1800,22 @@ class Parser extends Tapable { } enterObjectPattern(pattern, onIdent) { - for(let propIndex = 0, len = pattern.properties.length; propIndex < len; propIndex++) { + for ( + let propIndex = 0, len = pattern.properties.length; + propIndex < len; + propIndex++ + ) { const prop = pattern.properties[propIndex]; this.enterPattern(prop.value, onIdent); } } enterArrayPattern(pattern, onIdent) { - for(let elementIndex = 0, len = pattern.elements.length; elementIndex < len; elementIndex++) { + for ( + let elementIndex = 0, len = pattern.elements.length; + elementIndex < len; + elementIndex++ + ) { const element = pattern.elements[elementIndex]; this.enterPattern(element, onIdent); } @@ -1676,12 +1832,11 @@ class Parser extends Tapable { evaluateExpression(expression) { try { const hook = this.hooks.evaluate.get(expression.type); - if(hook !== undefined) { + if (hook !== undefined) { const result = hook.call(expression); - if(result !== undefined) - return result; + if (result !== undefined) return result; } - } catch(e) { + } catch (e) { console.warn(e); // ignore error } @@ -1689,32 +1844,40 @@ class Parser extends Tapable { } parseString(expression) { - switch(expression.type) { + switch (expression.type) { case "BinaryExpression": - if(expression.operator === "+") - return this.parseString(expression.left) + this.parseString(expression.right); + if (expression.operator === "+") + return ( + this.parseString(expression.left) + + this.parseString(expression.right) + ); break; case "Literal": return expression.value + ""; } - throw new Error(expression.type + " is not supported as parameter for require"); + throw new Error( + expression.type + " is not supported as parameter for require" + ); } parseCalculatedString(expression) { - switch(expression.type) { + switch (expression.type) { case "BinaryExpression": - if(expression.operator === "+") { + if (expression.operator === "+") { const left = this.parseCalculatedString(expression.left); const right = this.parseCalculatedString(expression.right); - if(left.code) { + if (left.code) { return { range: left.range, value: left.value, code: true }; - } else if(right.code) { + } else if (right.code) { return { - range: [left.range[0], right.range ? right.range[1] : left.range[1]], + range: [ + left.range[0], + right.range ? right.range[1] : left.range[1] + ], value: left.value + right.value, code: true }; @@ -1726,27 +1889,22 @@ class Parser extends Tapable { } } break; - case "ConditionalExpression": - { - const consequent = this.parseCalculatedString(expression.consequent); - const alternate = this.parseCalculatedString(expression.alternate); - const items = []; - if(consequent.conditional) - items.push(...consequent.conditional); - else if(!consequent.code) - items.push(consequent); - else break; - if(alternate.conditional) - items.push(...alternate.conditional); - else if(!alternate.code) - items.push(alternate); - else break; - return { - value: "", - code: true, - conditional: items - }; - } + case "ConditionalExpression": { + const consequent = this.parseCalculatedString(expression.consequent); + const alternate = this.parseCalculatedString(expression.alternate); + const items = []; + if (consequent.conditional) items.push(...consequent.conditional); + else if (!consequent.code) items.push(consequent); + else break; + if (alternate.conditional) items.push(...alternate.conditional); + else if (!alternate.code) items.push(alternate); + else break; + return { + value: "", + code: true, + conditional: items + }; + } case "Literal": return { range: expression.range, @@ -1762,7 +1920,7 @@ class Parser extends Tapable { parse(source, initialState) { let ast; let comments; - if(typeof source === "object" && source !== null) { + if (typeof source === "object" && source !== null) { ast = source; comments = source.comments; } else { @@ -1784,9 +1942,9 @@ class Parser extends Tapable { definitions: new StackedSetMap(), renames: new StackedSetMap() }; - const state = this.state = initialState || {}; + const state = (this.state = initialState || {}); this.comments = comments; - if(this.hooks.program.call(ast, comments) === undefined) { + if (this.hooks.program.call(ast, comments) === undefined) { this.detectStrictMode(ast.body); this.prewalkStatements(ast.body); this.walkStatements(ast.body); @@ -1800,25 +1958,29 @@ class Parser extends Tapable { evaluate(source) { const ast = Parser.parse("(" + source + ")", { sourceType: this.sourceType, - locations: false, + locations: false }); - if(ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") + if (ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") throw new Error("evaluate: Source is not a expression"); return this.evaluateExpression(ast.body[0].expression); } getComments(range) { - return this.comments.filter(comment => comment.range[0] >= range[0] && comment.range[1] <= range[1]); + return this.comments.filter( + comment => comment.range[0] >= range[0] && comment.range[1] <= range[1] + ); } getCommentOptions(range) { const comments = this.getComments(range); - if(comments.length === 0) return null; + if (comments.length === 0) return null; const options = comments.map(comment => { try { - let val = vm.runInNewContext(`(function(){return {${comment.value}};})()`); + let val = vm.runInNewContext( + `(function(){return {${comment.value}};})()` + ); return val; - } catch(e) { + } catch (e) { return {}; } }); @@ -1828,28 +1990,32 @@ class Parser extends Tapable { getNameForExpression(expression) { let expr = expression; const exprName = []; - while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) { + while ( + expr.type === "MemberExpression" && + expr.property.type === (expr.computed ? "Literal" : "Identifier") + ) { exprName.push(expr.computed ? expr.property.value : expr.property.name); expr = expr.object; } let free; - if(expr.type === "Identifier") { + if (expr.type === "Identifier") { free = !this.scope.definitions.has(expr.name); exprName.push(this.scope.renames.get(expr.name) || expr.name); - } else if(expr.type === "ThisExpression" && this.scope.renames.get("this")) { + } else if ( + expr.type === "ThisExpression" && + this.scope.renames.get("this") + ) { free = true; exprName.push(this.scope.renames.get("this")); - } else if(expr.type === "ThisExpression") { + } else if (expr.type === "ThisExpression") { free = false; exprName.push("this"); } else { return null; } let prefix = ""; - for(let i = exprName.length - 1; i >= 2; i--) - prefix += exprName[i] + "."; - if(exprName.length > 1) - prefix += exprName[1]; + for (let i = exprName.length - 1; i >= 2; i--) prefix += exprName[i] + "."; + if (exprName.length > 1) prefix += exprName[1]; const name = prefix ? prefix + "." + exprName[0] : exprName[0]; const nameGeneral = prefix; return { @@ -1861,9 +2027,13 @@ class Parser extends Tapable { static parse(code, options) { const type = options ? options.sourceType : "module"; - const parserOptions = Object.assign(Object.create(null), defaultParserOptions, options); + const parserOptions = Object.assign( + Object.create(null), + defaultParserOptions, + options + ); - if(type === "auto") { + if (type === "auto") { parserOptions.sourceType = "module"; } @@ -1872,23 +2042,23 @@ class Parser extends Tapable { let threw = false; try { ast = acorn.parse(code, parserOptions); - } catch(e) { + } catch (e) { error = e; threw = true; } - if(threw && type === "auto") { + if (threw && type === "auto") { parserOptions.sourceType = "script"; - if(Array.isArray(parserOptions.onComment)) { + if (Array.isArray(parserOptions.onComment)) { parserOptions.onComment.length = 0; } try { ast = acorn.parse(code, parserOptions); threw = false; - } catch(e) {} + } catch (e) {} } - if(threw) { + if (threw) { throw error; } diff --git a/lib/ParserHelpers.js b/lib/ParserHelpers.js index 2ccd12150..1098cb99c 100644 --- a/lib/ParserHelpers.js +++ b/lib/ParserHelpers.js @@ -12,7 +12,7 @@ const UnsupportedFeatureWarning = require("./UnsupportedFeatureWarning"); const ParserHelpers = exports; ParserHelpers.addParsedVariableToModule = (parser, name, expression) => { - if(!parser.state.current.addVariable) return false; + if (!parser.state.current.addVariable) return false; var deps = []; parser.parse(expression, { current: { @@ -29,7 +29,7 @@ ParserHelpers.addParsedVariableToModule = (parser, name, expression) => { ParserHelpers.requireFileAsExpression = (context, pathToModule) => { var moduleJsPath = path.relative(context, pathToModule); - if(!/^[A-Z]:/i.test(moduleJsPath)) { + if (!/^[A-Z]:/i.test(moduleJsPath)) { moduleJsPath = "./" + moduleJsPath.replace(/\\/g, "/"); } return "require(" + JSON.stringify(moduleJsPath) + ")"; @@ -61,15 +61,19 @@ ParserHelpers.evaluateToString = value => { ParserHelpers.evaluateToBoolean = value => { return function booleanExpression(expr) { - return new BasicEvaluatedExpression().setBoolean(value).setRange(expr.range); + return new BasicEvaluatedExpression() + .setBoolean(value) + .setRange(expr.range); }; }; ParserHelpers.evaluateToIdentifier = (identifier, truthy) => { return function identifierExpression(expr) { - let evex = new BasicEvaluatedExpression().setIdentifier(identifier).setRange(expr.range); - if(truthy === true) evex = evex.setTruthy(); - else if(truthy === false) evex = evex.setFalsy(); + let evex = new BasicEvaluatedExpression() + .setIdentifier(identifier) + .setRange(expr.range); + if (truthy === true) evex = evex.setTruthy(); + else if (truthy === false) evex = evex.setFalsy(); return evex; }; }; @@ -79,8 +83,10 @@ ParserHelpers.expressionIsUnsupported = (parser, message) => { var dep = new ConstDependency("(void 0)", expr.range, false); dep.loc = expr.loc; parser.state.current.addDependency(dep); - if(!parser.state.module) return; - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, message)); + if (!parser.state.module) return; + parser.state.module.warnings.push( + new UnsupportedFeatureWarning(parser.state.module, message) + ); return true; }; }; diff --git a/lib/PrefetchPlugin.js b/lib/PrefetchPlugin.js index c1019169c..cc9d17c0c 100644 --- a/lib/PrefetchPlugin.js +++ b/lib/PrefetchPlugin.js @@ -6,9 +6,8 @@ const PrefetchDependency = require("./dependencies/PrefetchDependency"); class PrefetchPlugin { - constructor(context, request) { - if(!request) { + if (!request) { this.request = context; } else { this.context = context; @@ -17,15 +16,22 @@ class PrefetchPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("PrefetchPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(PrefetchDependency, normalModuleFactory); - }); + compiler.hooks.compilation.tap( + "PrefetchPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + PrefetchDependency, + normalModuleFactory + ); + } + ); compiler.hooks.make.tapAsync("PrefetchPlugin", (compilation, callback) => { - compilation.prefetch(this.context || compiler.context, new PrefetchDependency(this.request), callback); + compilation.prefetch( + this.context || compiler.context, + new PrefetchDependency(this.request), + callback + ); }); } - } module.exports = PrefetchPlugin; diff --git a/lib/ProgressPlugin.js b/lib/ProgressPlugin.js index 51a75075c..5cac8ee9e 100644 --- a/lib/ProgressPlugin.js +++ b/lib/ProgressPlugin.js @@ -5,7 +5,6 @@ "use strict"; const createDefaultHandler = profile => { - let lineCaretPosition = 0; let lastState; let lastStateTime; @@ -13,31 +12,31 @@ const createDefaultHandler = profile => { const defaultHandler = (percentage, msg, ...args) => { let state = msg; const details = args; - if(percentage < 1) { + if (percentage < 1) { percentage = Math.floor(percentage * 100); msg = `${percentage}% ${msg}`; - if(percentage < 100) { + if (percentage < 100) { msg = ` ${msg}`; } - if(percentage < 10) { + if (percentage < 10) { msg = ` ${msg}`; } - for(let detail of details) { - if(!detail) continue; - if(detail.length > 40) { + for (let detail of details) { + if (!detail) continue; + if (detail.length > 40) { detail = `...${detail.substr(detail.length - 37)}`; } msg += ` ${detail}`; } } - if(profile) { + if (profile) { state = state.replace(/^\d+\/\d+\s+/, ""); - if(percentage === 0) { + if (percentage === 0) { lastState = null; lastStateTime = Date.now(); - } else if(state !== lastState || percentage === 1) { + } else if (state !== lastState || percentage === 1) { const now = Date.now(); - if(lastState) { + if (lastState) { const stateMsg = `${now - lastStateTime}ms ${lastState}`; goToLineStart(stateMsg); process.stderr.write(stateMsg + "\n"); @@ -53,24 +52,22 @@ const createDefaultHandler = profile => { const goToLineStart = nextMessage => { let str = ""; - for(; lineCaretPosition > nextMessage.length; lineCaretPosition--) { + for (; lineCaretPosition > nextMessage.length; lineCaretPosition--) { str += "\b \b"; } - for(var i = 0; i < lineCaretPosition; i++) { + for (var i = 0; i < lineCaretPosition; i++) { str += "\b"; } lineCaretPosition = nextMessage.length; - if(str) process.stderr.write(str); + if (str) process.stderr.write(str); }; return defaultHandler; - }; class ProgressPlugin { - constructor(options) { - if(typeof options === "function") { + if (typeof options === "function") { options = { handler: options }; @@ -82,13 +79,15 @@ class ProgressPlugin { apply(compiler) { const handler = this.handler || createDefaultHandler(this.profile); - if(compiler.compilers) { + if (compiler.compilers) { const states = new Array(compiler.compilers.length); compiler.compilers.forEach((compiler, idx) => { new ProgressPlugin((p, msg, ...args) => { states[idx] = args; handler( - states.map(state => state && state[0] || 0).reduce((a, b) => a + b) / states.length, + states + .map(state => (state && state[0]) || 0) + .reduce((a, b) => a + b) / states.length, `[${idx}] ${msg}`, ...args ); @@ -102,7 +101,7 @@ class ProgressPlugin { const update = module => { handler( - 0.1 + (doneModules / Math.max(lastModulesCount, moduleCount)) * 0.6, + 0.1 + doneModules / Math.max(lastModulesCount, moduleCount) * 0.6, "building modules", `${doneModules}/${moduleCount} modules`, `${activeModules.length} active`, @@ -113,14 +112,14 @@ class ProgressPlugin { const moduleDone = module => { doneModules++; const ident = module.identifier(); - if(ident) { + if (ident) { const idx = activeModules.indexOf(ident); - if(idx >= 0) activeModules.splice(idx, 1); + if (idx >= 0) activeModules.splice(idx, 1); } update(); }; - compiler.hooks.compilation.tap("ProgressPlugin", (compilation) => { - if(compilation.compiler.isChild()) return; + compiler.hooks.compilation.tap("ProgressPlugin", compilation => { + if (compilation.compiler.isChild()) return; lastModulesCount = moduleCount; moduleCount = 0; doneModules = 0; @@ -128,7 +127,7 @@ class ProgressPlugin { compilation.hooks.buildModule.tap("ProgressPlugin", module => { moduleCount++; const ident = module.identifier(); - if(ident) { + if (ident) { activeModules.push(ident); } update(); @@ -196,7 +195,7 @@ class ProgressPlugin { handler(percentage, title); }, tap: (context, tap) => { - if(context) { + if (context) { // p is percentage from 0 to 1 // args is any number of messages in a hierarchical matter context.reportProgress = (p, ...args) => { @@ -215,7 +214,7 @@ class ProgressPlugin { handler(0.95, "emitting"); }, tap: (context, tap) => { - if(context) { + if (context) { context.reportProgress = (p, ...args) => { handler(0.95, "emitting", tap.name, ...args); }; diff --git a/lib/ProvidePlugin.js b/lib/ProvidePlugin.js index 212efcd2c..b09d8c864 100644 --- a/lib/ProvidePlugin.js +++ b/lib/ProvidePlugin.js @@ -16,45 +16,71 @@ class ProvidePlugin { apply(compiler) { const definitions = this.definitions; - compiler.hooks.compilation.tap("ProvidePlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - const handler = (parser, parserOptions) => { - Object.keys(definitions).forEach(name => { - var request = [].concat(definitions[name]); - var splittedName = name.split("."); - if(splittedName.length > 0) { - splittedName.slice(1).forEach((_, i) => { - const name = splittedName.slice(0, i + 1).join("."); - parser.hooks.canRename.for(name).tap("ProvidePlugin", ParserHelpers.approve); + compiler.hooks.compilation.tap( + "ProvidePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + const handler = (parser, parserOptions) => { + Object.keys(definitions).forEach(name => { + var request = [].concat(definitions[name]); + var splittedName = name.split("."); + if (splittedName.length > 0) { + splittedName.slice(1).forEach((_, i) => { + const name = splittedName.slice(0, i + 1).join("."); + parser.hooks.canRename + .for(name) + .tap("ProvidePlugin", ParserHelpers.approve); + }); + } + parser.hooks.expression.for(name).tap("ProvidePlugin", expr => { + let nameIdentifier = name; + const scopedName = name.includes("."); + let expression = `require(${JSON.stringify(request[0])})`; + if (scopedName) { + nameIdentifier = `__webpack_provided_${name.replace( + /\./g, + "_dot_" + )}`; + } + if (request.length > 1) { + expression += request + .slice(1) + .map(r => `[${JSON.stringify(r)}]`) + .join(""); + } + if ( + !ParserHelpers.addParsedVariableToModule( + parser, + nameIdentifier, + expression + ) + ) { + return false; + } + if (scopedName) { + ParserHelpers.toConstantDependency(parser, nameIdentifier)( + expr + ); + } + return true; }); - } - parser.hooks.expression.for(name).tap("ProvidePlugin", expr => { - let nameIdentifier = name; - const scopedName = name.includes("."); - let expression = `require(${JSON.stringify(request[0])})`; - if(scopedName) { - nameIdentifier = `__webpack_provided_${name.replace(/\./g, "_dot_")}`; - } - if(request.length > 1) { - expression += request.slice(1).map(r => `[${JSON.stringify(r)}]`).join(""); - } - if(!ParserHelpers.addParsedVariableToModule(parser, nameIdentifier, expression)) { - return false; - } - if(scopedName) { - ParserHelpers.toConstantDependency(parser, nameIdentifier)(expr); - } - return true; }); - }); - }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("ProvidePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ProvidePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("ProvidePlugin", handler); - }); + }; + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ProvidePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ProvidePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ProvidePlugin", handler); + } + ); } } module.exports = ProvidePlugin; diff --git a/lib/RawModule.js b/lib/RawModule.js index a7ea6db6e..85f1a0ead 100644 --- a/lib/RawModule.js +++ b/lib/RawModule.js @@ -9,7 +9,6 @@ const OriginalSource = require("webpack-sources").OriginalSource; const RawSource = require("webpack-sources").RawSource; module.exports = class RawModule extends Module { - constructor(source, identifier, readableIdentifier) { super("javascript/dynamic", null); this.sourceStr = source; @@ -44,10 +43,9 @@ module.exports = class RawModule extends Module { } source() { - if(this.useSourceMap) + if (this.useSourceMap) return new OriginalSource(this.sourceStr, this.identifier()); - else - return new RawSource(this.sourceStr); + else return new RawSource(this.sourceStr); } updateHash(hash) { diff --git a/lib/RecordIdsPlugin.js b/lib/RecordIdsPlugin.js index b5f1b6552..be249ddd2 100644 --- a/lib/RecordIdsPlugin.js +++ b/lib/RecordIdsPlugin.js @@ -13,105 +13,147 @@ class RecordIdsPlugin { apply(compiler) { const portableIds = this.options.portableIds; - compiler.hooks.compilation.tap("RecordIdsPlugin", (compilation) => { - compilation.hooks.recordModules.tap("RecordIdsPlugin", (modules, records) => { - if(!records.modules) records.modules = {}; - if(!records.modules.byIdentifier) records.modules.byIdentifier = {}; - if(!records.modules.usedIds) records.modules.usedIds = {}; - for(const module of modules) { - const identifier = portableIds ? identifierUtils.makePathsRelative(compiler.context, module.identifier(), compilation.cache) : module.identifier(); - records.modules.byIdentifier[identifier] = module.id; - records.modules.usedIds[module.id] = module.id; - } - }); - compilation.hooks.reviveModules.tap("RecordIdsPlugin", (modules, records) => { - if(!records.modules) return; - if(records.modules.byIdentifier) { - const usedIds = new Set(); - for(const module of modules) { - if(module.id !== null) continue; - const identifier = portableIds ? identifierUtils.makePathsRelative(compiler.context, module.identifier(), compilation.cache) : module.identifier(); - const id = records.modules.byIdentifier[identifier]; - if(id === undefined) continue; - if(usedIds.has(id)) continue; - usedIds.add(id); - module.id = id; + compiler.hooks.compilation.tap("RecordIdsPlugin", compilation => { + compilation.hooks.recordModules.tap( + "RecordIdsPlugin", + (modules, records) => { + if (!records.modules) records.modules = {}; + if (!records.modules.byIdentifier) records.modules.byIdentifier = {}; + if (!records.modules.usedIds) records.modules.usedIds = {}; + for (const module of modules) { + const identifier = portableIds + ? identifierUtils.makePathsRelative( + compiler.context, + module.identifier(), + compilation.cache + ) + : module.identifier(); + records.modules.byIdentifier[identifier] = module.id; + records.modules.usedIds[module.id] = module.id; } } - if(Array.isArray(records.modules.usedIds)) - compilation.usedModuleIds = new Set(records.modules.usedIds); - }); + ); + compilation.hooks.reviveModules.tap( + "RecordIdsPlugin", + (modules, records) => { + if (!records.modules) return; + if (records.modules.byIdentifier) { + const usedIds = new Set(); + for (const module of modules) { + if (module.id !== null) continue; + const identifier = portableIds + ? identifierUtils.makePathsRelative( + compiler.context, + module.identifier(), + compilation.cache + ) + : module.identifier(); + const id = records.modules.byIdentifier[identifier]; + if (id === undefined) continue; + if (usedIds.has(id)) continue; + usedIds.add(id); + module.id = id; + } + } + if (Array.isArray(records.modules.usedIds)) + compilation.usedModuleIds = new Set(records.modules.usedIds); + } + ); const getModuleIdentifier = module => { - if(portableIds) - return identifierUtils.makePathsRelative(compiler.context, module.identifier(), compilation.cache); + if (portableIds) + return identifierUtils.makePathsRelative( + compiler.context, + module.identifier(), + compilation.cache + ); return module.identifier(); }; const getChunkSources = chunk => { const sources = []; - for(const chunkGroup of chunk.groupsIterable) { + for (const chunkGroup of chunk.groupsIterable) { const index = chunkGroup.chunks.indexOf(chunk); - for(const origin of chunkGroup.origins) { - if(origin.module) { - if(origin.request) - sources.push(`${index} ${getModuleIdentifier(origin.module)} ${origin.request}`); - else if(typeof origin.loc === "string") - sources.push(`${index} ${getModuleIdentifier(origin.module)} ${origin.loc}`); - else if(origin.loc && typeof origin.loc === "object" && origin.loc.start) - sources.push(`${index} ${getModuleIdentifier(origin.module)} ${JSON.stringify(origin.loc.start)}`); + for (const origin of chunkGroup.origins) { + if (origin.module) { + if (origin.request) + sources.push( + `${index} ${getModuleIdentifier(origin.module)} ${ + origin.request + }` + ); + else if (typeof origin.loc === "string") + sources.push( + `${index} ${getModuleIdentifier(origin.module)} ${origin.loc}` + ); + else if ( + origin.loc && + typeof origin.loc === "object" && + origin.loc.start + ) + sources.push( + `${index} ${getModuleIdentifier( + origin.module + )} ${JSON.stringify(origin.loc.start)}` + ); } } } return sources; }; - compilation.hooks.recordChunks.tap("RecordIdsPlugin", (chunks, records) => { - if(!records.chunks) records.chunks = {}; - if(!records.chunks.byName) records.chunks.byName = {}; - if(!records.chunks.bySource) records.chunks.bySource = {}; - const usedIds = new Set(); - for(const chunk of chunks) { - const name = chunk.name; - if(name) records.chunks.byName[name] = chunk.id; - const sources = getChunkSources(chunk); - for(const source of sources) { - records.chunks.bySource[source] = chunk.id; - } - usedIds.add(chunk.id); - } - records.chunks.usedIds = Array.from(usedIds); - }); - compilation.hooks.reviveChunks.tap("RecordIdsPlugin", (chunks, records) => { - if(!records.chunks) return; - const usedIds = new Set(); - if(records.chunks.byName) { - for(const chunk of chunks) { - if(chunk.id !== null) continue; - if(!chunk.name) continue; - const id = records.chunks.byName[chunk.name]; - if(id === undefined) continue; - if(usedIds.has(id)) continue; - usedIds.add(id); - chunk.id = id; - } - } - if(records.chunks.bySource) { - for(const chunk of chunks) { + compilation.hooks.recordChunks.tap( + "RecordIdsPlugin", + (chunks, records) => { + if (!records.chunks) records.chunks = {}; + if (!records.chunks.byName) records.chunks.byName = {}; + if (!records.chunks.bySource) records.chunks.bySource = {}; + const usedIds = new Set(); + for (const chunk of chunks) { + const name = chunk.name; + if (name) records.chunks.byName[name] = chunk.id; const sources = getChunkSources(chunk); - for(const source of sources) { - const id = records.chunks.bySource[source]; - if(id === undefined) continue; - if(usedIds[id]) continue; - usedIds[id] = true; + for (const source of sources) { + records.chunks.bySource[source] = chunk.id; + } + usedIds.add(chunk.id); + } + records.chunks.usedIds = Array.from(usedIds); + } + ); + compilation.hooks.reviveChunks.tap( + "RecordIdsPlugin", + (chunks, records) => { + if (!records.chunks) return; + const usedIds = new Set(); + if (records.chunks.byName) { + for (const chunk of chunks) { + if (chunk.id !== null) continue; + if (!chunk.name) continue; + const id = records.chunks.byName[chunk.name]; + if (id === undefined) continue; + if (usedIds.has(id)) continue; + usedIds.add(id); chunk.id = id; - break; } } + if (records.chunks.bySource) { + for (const chunk of chunks) { + const sources = getChunkSources(chunk); + for (const source of sources) { + const id = records.chunks.bySource[source]; + if (id === undefined) continue; + if (usedIds[id]) continue; + usedIds[id] = true; + chunk.id = id; + break; + } + } + } + if (Array.isArray(records.chunks.usedIds)) + compilation.usedChunkIds = new Set(records.chunks.usedIds); } - if(Array.isArray(records.chunks.usedIds)) - compilation.usedChunkIds = new Set(records.chunks.usedIds); - }); + ); }); } } diff --git a/lib/RequestShortener.js b/lib/RequestShortener.js index bd480a6dd..0e2d3d47d 100644 --- a/lib/RequestShortener.js +++ b/lib/RequestShortener.js @@ -11,11 +11,11 @@ const SEPARATOR_REGEXP = /[/\\]$/; const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g; const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g; -const normalizeBackSlashDirection = (request) => { +const normalizeBackSlashDirection = request => { return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/"); }; -const createRegExpForPath = (path) => { +const createRegExpForPath = path => { const regexpTypePartial = path.replace(PATH_CHARS_REGEXP, "\\$&"); return new RegExp(`(^|!)${regexpTypePartial}`, "g"); }; @@ -23,22 +23,27 @@ const createRegExpForPath = (path) => { class RequestShortener { constructor(directory) { directory = normalizeBackSlashDirection(directory); - if(SEPARATOR_REGEXP.test(directory)) directory = directory.substr(0, directory.length - 1); + if (SEPARATOR_REGEXP.test(directory)) + directory = directory.substr(0, directory.length - 1); - if(directory) { + if (directory) { this.currentDirectoryRegExp = createRegExpForPath(directory); } const dirname = path.dirname(directory); const endsWithSeperator = SEPARATOR_REGEXP.test(dirname); - const parentDirectory = endsWithSeperator ? dirname.substr(0, dirname.length - 1) : dirname; - if(parentDirectory && parentDirectory !== directory) { + const parentDirectory = endsWithSeperator + ? dirname.substr(0, dirname.length - 1) + : dirname; + if (parentDirectory && parentDirectory !== directory) { this.parentDirectoryRegExp = createRegExpForPath(parentDirectory); } - if(__dirname.length >= 2) { + if (__dirname.length >= 2) { const buildins = normalizeBackSlashDirection(path.join(__dirname, "..")); - const buildinsAsModule = this.currentDirectoryRegExp && this.currentDirectoryRegExp.test(buildins); + const buildinsAsModule = + this.currentDirectoryRegExp && + this.currentDirectoryRegExp.test(buildins); this.buildinsAsModule = buildinsAsModule; this.buildinsRegExp = createRegExpForPath(buildins); } @@ -47,17 +52,17 @@ class RequestShortener { } shorten(request) { - if(!request) return request; + if (!request) return request; const cacheEntry = this.cache.get(request); - if(cacheEntry !== undefined) return cacheEntry; + if (cacheEntry !== undefined) return cacheEntry; let result = normalizeBackSlashDirection(request); - if(this.buildinsAsModule && this.buildinsRegExp) + if (this.buildinsAsModule && this.buildinsRegExp) result = result.replace(this.buildinsRegExp, "!(webpack)"); - if(this.currentDirectoryRegExp) + if (this.currentDirectoryRegExp) result = result.replace(this.currentDirectoryRegExp, "!."); - if(this.parentDirectoryRegExp) + if (this.parentDirectoryRegExp) result = result.replace(this.parentDirectoryRegExp, "!.."); - if(!this.buildinsAsModule && this.buildinsRegExp) + if (!this.buildinsAsModule && this.buildinsRegExp) result = result.replace(this.buildinsRegExp, "!(webpack)"); result = result.replace(INDEX_JS_REGEXP, "$1"); result = result.replace(FRONT_OR_BACK_BANG_REGEXP, ""); diff --git a/lib/RequireJsStuffPlugin.js b/lib/RequireJsStuffPlugin.js index 585fdb290..84793c8a9 100644 --- a/lib/RequireJsStuffPlugin.js +++ b/lib/RequireJsStuffPlugin.js @@ -9,26 +9,61 @@ const ConstDependency = require("./dependencies/ConstDependency"); const NullFactory = require("./NullFactory"); module.exports = class RequireJsStuffPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("RequireJsStuffPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.requireJs !== "undefined" && !parserOptions.requireJs) - return; + compiler.hooks.compilation.tap( + "RequireJsStuffPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.requireJs !== "undefined" && + !parserOptions.requireJs + ) + return; - parser.hooks.call.for("require.config").tap("RequireJsStuffPlugin", ParserHelpers.toConstantDependency(parser, "undefined")); - parser.hooks.call.for("requirejs.config").tap("RequireJsStuffPlugin", ParserHelpers.toConstantDependency(parser, "undefined")); + parser.hooks.call + .for("require.config") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependency(parser, "undefined") + ); + parser.hooks.call + .for("requirejs.config") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependency(parser, "undefined") + ); - parser.hooks.expression.for("require.version").tap("RequireJsStuffPlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("0.0.0"))); - parser.hooks.expression.for("requirejs.onError").tap("RequireJsStuffPlugin", ParserHelpers.toConstantDependencyWithWebpackRequire(parser, "__webpack_require__.oe")); - }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("RequireJsStuffPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("RequireJsStuffPlugin", handler); - }); + parser.hooks.expression + .for("require.version") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("0.0.0") + ) + ); + parser.hooks.expression + .for("requirejs.onError") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.oe" + ) + ); + }; + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireJsStuffPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireJsStuffPlugin", handler); + } + ); } - }; diff --git a/lib/ResolverFactory.js b/lib/ResolverFactory.js index 2675bb6da..6d3aedd03 100644 --- a/lib/ResolverFactory.js +++ b/lib/ResolverFactory.js @@ -14,19 +14,29 @@ module.exports = class ResolverFactory extends Tapable { constructor() { super(); this.hooks = { - resolveOptions: new HookMap(() => new SyncWaterfallHook(["resolveOptions"])), - resolver: new HookMap(() => new SyncHook(["resolver", "resolveOptions"])), + resolveOptions: new HookMap( + () => new SyncWaterfallHook(["resolveOptions"]) + ), + resolver: new HookMap(() => new SyncHook(["resolver", "resolveOptions"])) }; this._pluginCompat.tap("ResolverFactory", options => { let match; match = /^resolve-options (.+)$/.exec(options.name); - if(match) { - this.hooks.resolveOptions.tap(match[1], options.fn.name || "unnamed compat plugin", options.fn); + if (match) { + this.hooks.resolveOptions.tap( + match[1], + options.fn.name || "unnamed compat plugin", + options.fn + ); return true; } match = /^resolver (.+)$/.exec(options.name); - if(match) { - this.hooks.resolver.tap(match[1], options.fn.name || "unnamed compat plugin", options.fn); + if (match) { + this.hooks.resolver.tap( + match[1], + options.fn.name || "unnamed compat plugin", + options.fn + ); return true; } }); @@ -36,10 +46,10 @@ module.exports = class ResolverFactory extends Tapable { get(type, resolveOptions) { const cachedResolver = this.cache1.get(resolveOptions); - if(cachedResolver) return cachedResolver(); + if (cachedResolver) return cachedResolver(); const ident = `${type}|${JSON.stringify(resolveOptions)}`; const resolver = this.cache2.get(ident); - if(resolver) return resolver; + if (resolver) return resolver; const newResolver = this._create(type, resolveOptions); this.cache2.set(ident, newResolver); return newResolver; @@ -48,7 +58,7 @@ module.exports = class ResolverFactory extends Tapable { _create(type, resolveOptions) { resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions); const resolver = Factory.createResolver(resolveOptions); - if(!resolver) { + if (!resolver) { throw new Error("No resolver created"); } this.hooks.resolver.for(type).call(resolver, resolveOptions); diff --git a/lib/RuleSet.js b/lib/RuleSet.js index 484fa0c44..bf0f2bfdf 100644 --- a/lib/RuleSet.js +++ b/lib/RuleSet.js @@ -82,9 +82,8 @@ const notMatcher = matcher => { const orMatcher = items => { return function(str) { - for(let i = 0; i < items.length; i++) { - if(items[i](str)) - return true; + for (let i = 0; i < items.length; i++) { + if (items[i](str)) return true; } return false; }; @@ -92,9 +91,8 @@ const orMatcher = items => { const andMatcher = items => { return function(str) { - for(let i = 0; i < items.length; i++) { - if(!items[i](str)) - return false; + for (let i = 0; i < items.length; i++) { + if (!items[i](str)) return false; } return true; }; @@ -107,11 +105,11 @@ module.exports = class RuleSet { } static normalizeRules(rules, refs, ident) { - if(Array.isArray(rules)) { + if (Array.isArray(rules)) { return rules.map((rule, idx) => { return RuleSet.normalizeRule(rule, refs, `${ident}-${idx}`); }); - } else if(rules) { + } else if (rules) { return [RuleSet.normalizeRule(rules, refs, ident)]; } else { return []; @@ -119,16 +117,24 @@ module.exports = class RuleSet { } static normalizeRule(rule, refs, ident) { - if(typeof rule === "string") + if (typeof rule === "string") return { - use: [{ - loader: rule - }] + use: [ + { + loader: rule + } + ] }; - if(!rule) + if (!rule) throw new Error("Unexcepted null when object was expected as rule"); - if(typeof rule !== "object") - throw new Error("Unexcepted " + typeof rule + " when object was expected as rule (" + rule + ")"); + if (typeof rule !== "object") + throw new Error( + "Unexcepted " + + typeof rule + + " when object was expected as rule (" + + rule + + ")" + ); const newRule = {}; let useSource; @@ -136,18 +142,40 @@ module.exports = class RuleSet { let condition; const checkUseSource = newSource => { - if(useSource && useSource !== newSource) - throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one result source (provided " + newSource + " and " + useSource + ")"))); + if (useSource && useSource !== newSource) + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "Rule can only have one result source (provided " + + newSource + + " and " + + useSource + + ")" + ) + ) + ); useSource = newSource; }; const checkResourceSource = newSource => { - if(resourceSource && resourceSource !== newSource) - throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one resource source (provided " + newSource + " and " + resourceSource + ")"))); + if (resourceSource && resourceSource !== newSource) + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "Rule can only have one resource source (provided " + + newSource + + " and " + + resourceSource + + ")" + ) + ) + ); resourceSource = newSource; }; - if(rule.test || rule.include || rule.exclude) { + if (rule.test || rule.include || rule.exclude) { checkResourceSource("test + include + exclude"); condition = { test: rule.test, @@ -156,88 +184,135 @@ module.exports = class RuleSet { }; try { newRule.resource = RuleSet.normalizeCondition(condition); - } catch(error) { + } catch (error) { throw new Error(RuleSet.buildErrorMessage(condition, error)); } } - if(rule.resource) { + if (rule.resource) { checkResourceSource("resource"); try { newRule.resource = RuleSet.normalizeCondition(rule.resource); - } catch(error) { + } catch (error) { throw new Error(RuleSet.buildErrorMessage(rule.resource, error)); } } - if(rule.resourceQuery) { + if (rule.resourceQuery) { try { newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery); - } catch(error) { + } catch (error) { throw new Error(RuleSet.buildErrorMessage(rule.resourceQuery, error)); } } - if(rule.compiler) { + if (rule.compiler) { try { newRule.compiler = RuleSet.normalizeCondition(rule.compiler); - } catch(error) { + } catch (error) { throw new Error(RuleSet.buildErrorMessage(rule.compiler, error)); } } - if(rule.issuer) { + if (rule.issuer) { try { newRule.issuer = RuleSet.normalizeCondition(rule.issuer); - } catch(error) { + } catch (error) { throw new Error(RuleSet.buildErrorMessage(rule.issuer, error)); } } - if(rule.loader && rule.loaders) - throw new Error(RuleSet.buildErrorMessage(rule, new Error("Provided loader and loaders for rule (use only one of them)"))); + if (rule.loader && rule.loaders) + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "Provided loader and loaders for rule (use only one of them)" + ) + ) + ); const loader = rule.loaders || rule.loader; - if(typeof loader === "string" && !rule.options && !rule.query) { + if (typeof loader === "string" && !rule.options && !rule.query) { checkUseSource("loader"); newRule.use = RuleSet.normalizeUse(loader.split("!"), ident); - } else if(typeof loader === "string" && (rule.options || rule.query)) { + } else if (typeof loader === "string" && (rule.options || rule.query)) { checkUseSource("loader + options/query"); - newRule.use = RuleSet.normalizeUse({ - loader: loader, - options: rule.options, - query: rule.query - }, ident); - } else if(loader && (rule.options || rule.query)) { - throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query cannot be used with loaders (use options for each array item)"))); - } else if(loader) { + newRule.use = RuleSet.normalizeUse( + { + loader: loader, + options: rule.options, + query: rule.query + }, + ident + ); + } else if (loader && (rule.options || rule.query)) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "options/query cannot be used with loaders (use options for each array item)" + ) + ) + ); + } else if (loader) { checkUseSource("loaders"); newRule.use = RuleSet.normalizeUse(loader, ident); - } else if(rule.options || rule.query) { - throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query provided without loader (use loader + options)"))); + } else if (rule.options || rule.query) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "options/query provided without loader (use loader + options)" + ) + ) + ); } - if(rule.use) { + if (rule.use) { checkUseSource("use"); newRule.use = RuleSet.normalizeUse(rule.use, ident); } - if(rule.rules) - newRule.rules = RuleSet.normalizeRules(rule.rules, refs, `${ident}-rules`); + if (rule.rules) + newRule.rules = RuleSet.normalizeRules( + rule.rules, + refs, + `${ident}-rules` + ); - if(rule.oneOf) - newRule.oneOf = RuleSet.normalizeRules(rule.oneOf, refs, `${ident}-oneOf`); + if (rule.oneOf) + newRule.oneOf = RuleSet.normalizeRules( + rule.oneOf, + refs, + `${ident}-oneOf` + ); - const keys = Object.keys(rule).filter((key) => { - return !["resource", "resourceQuery", "compiler", "test", "include", "exclude", "issuer", "loader", "options", "query", "loaders", "use", "rules", "oneOf"].includes(key); + const keys = Object.keys(rule).filter(key => { + return ![ + "resource", + "resourceQuery", + "compiler", + "test", + "include", + "exclude", + "issuer", + "loader", + "options", + "query", + "loaders", + "use", + "rules", + "oneOf" + ].includes(key); }); - for(const key of keys) { + for (const key of keys) { newRule[key] = rule[key]; } - if(Array.isArray(newRule.use)) { - for(const item of newRule.use) { - if(item.ident) { + if (Array.isArray(newRule.use)) { + for (const item of newRule.use) { + if (item.ident) { refs[item.ident] = item.options; } } @@ -247,17 +322,21 @@ module.exports = class RuleSet { } static buildErrorMessage(condition, error) { - const conditionAsText = JSON.stringify(condition, (key, value) => { - return value === undefined ? "undefined" : value; - }, 2); + const conditionAsText = JSON.stringify( + condition, + (key, value) => { + return value === undefined ? "undefined" : value; + }, + 2 + ); return error.message + " in " + conditionAsText; } static normalizeUse(use, ident) { - if(typeof use === "function") { + if (typeof use === "function") { return data => RuleSet.normalizeUse(use(data), ident); } - if(Array.isArray(use)) { + if (Array.isArray(use)) { return use .map((item, idx) => RuleSet.normalizeUse(item, `${ident}-${idx}`)) .reduce((arr, items) => arr.concat(items), []); @@ -267,7 +346,7 @@ module.exports = class RuleSet { static normalizeUseItemString(useItemString) { const idx = useItemString.indexOf("?"); - if(idx >= 0) { + if (idx >= 0) { return { loader: useItemString.substr(0, idx), options: useItemString.substr(idx + 1) @@ -279,32 +358,29 @@ module.exports = class RuleSet { } static normalizeUseItem(item, ident) { - if(typeof item === "string") { + if (typeof item === "string") { return RuleSet.normalizeUseItemString(item); } const newItem = {}; - if(item.options && item.query) + if (item.options && item.query) throw new Error("Provided options and query in use"); - if(!item.loader) - throw new Error("No loader specified"); + if (!item.loader) throw new Error("No loader specified"); newItem.options = item.options || item.query; - if(typeof newItem.options === "object" && newItem.options) { - if(newItem.options.ident) - newItem.ident = newItem.options.ident; - else - newItem.ident = ident; + if (typeof newItem.options === "object" && newItem.options) { + if (newItem.options.ident) newItem.ident = newItem.options.ident; + else newItem.ident = ident; } const keys = Object.keys(item).filter(function(key) { return !["options", "query"].includes(key); }); - for(const key of keys) { + for (const key of keys) { newItem[key] = item[key]; } @@ -312,43 +388,47 @@ module.exports = class RuleSet { } static normalizeCondition(condition) { - if(!condition) - throw new Error("Expected condition but got falsy value"); - if(typeof condition === "string") { + if (!condition) throw new Error("Expected condition but got falsy value"); + if (typeof condition === "string") { return str => str.indexOf(condition) === 0; } - if(typeof condition === "function") { + if (typeof condition === "function") { return condition; } - if(condition instanceof RegExp) { + if (condition instanceof RegExp) { return condition.test.bind(condition); } - if(Array.isArray(condition)) { + if (Array.isArray(condition)) { const items = condition.map(c => RuleSet.normalizeCondition(c)); return orMatcher(items); } - if(typeof condition !== "object") - throw Error("Unexcepted " + typeof condition + " when condition was expected (" + condition + ")"); + if (typeof condition !== "object") + throw Error( + "Unexcepted " + + typeof condition + + " when condition was expected (" + + condition + + ")" + ); const matchers = []; Object.keys(condition).forEach(key => { const value = condition[key]; - switch(key) { + switch (key) { case "or": case "include": case "test": - if(value) - matchers.push(RuleSet.normalizeCondition(value)); + if (value) matchers.push(RuleSet.normalizeCondition(value)); break; case "and": - if(value) { + if (value) { const items = value.map(c => RuleSet.normalizeCondition(c)); matchers.push(andMatcher(items)); } break; case "not": case "exclude": - if(value) { + if (value) { const matcher = RuleSet.normalizeCondition(value); matchers.push(notMatcher(matcher)); } @@ -357,56 +437,66 @@ module.exports = class RuleSet { throw new Error("Unexcepted property " + key + " in condition"); } }); - if(matchers.length === 0) + if (matchers.length === 0) throw new Error("Excepted condition but got " + condition); - if(matchers.length === 1) - return matchers[0]; + if (matchers.length === 1) return matchers[0]; return andMatcher(matchers); } exec(data) { const result = []; - this._run(data, { - rules: this.rules - }, result); + this._run( + data, + { + rules: this.rules + }, + result + ); return result; } _run(data, rule, result) { // test conditions - if(rule.resource && !data.resource) + if (rule.resource && !data.resource) return false; + if (rule.resourceQuery && !data.resourceQuery) return false; + if (rule.compiler && !data.compiler) return false; + if (rule.issuer && !data.issuer) return false; + if (rule.resource && !rule.resource(data.resource)) return false; + if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false; + if ( + data.resourceQuery && + rule.resourceQuery && + !rule.resourceQuery(data.resourceQuery) + ) return false; - if(rule.resourceQuery && !data.resourceQuery) - return false; - if(rule.compiler && !data.compiler) - return false; - if(rule.issuer && !data.issuer) - return false; - if(rule.resource && !rule.resource(data.resource)) - return false; - if(data.issuer && rule.issuer && !rule.issuer(data.issuer)) - return false; - if(data.resourceQuery && rule.resourceQuery && !rule.resourceQuery(data.resourceQuery)) - return false; - if(data.compiler && rule.compiler && !rule.compiler(data.compiler)) + if (data.compiler && rule.compiler && !rule.compiler(data.compiler)) return false; // apply - const keys = Object.keys(rule).filter((key) => { - return !["resource", "resourceQuery", "compiler", "issuer", "rules", "oneOf", "use", "enforce"].includes(key); + const keys = Object.keys(rule).filter(key => { + return ![ + "resource", + "resourceQuery", + "compiler", + "issuer", + "rules", + "oneOf", + "use", + "enforce" + ].includes(key); }); - for(const key of keys) { + for (const key of keys) { result.push({ type: key, value: rule[key] }); } - if(rule.use) { + if (rule.use) { const process = use => { - if(typeof use === "function") { + if (typeof use === "function") { process(use(data)); - } else if(Array.isArray(use)) { + } else if (Array.isArray(use)) { use.forEach(process); } else { result.push({ @@ -419,16 +509,15 @@ module.exports = class RuleSet { process(rule.use); } - if(rule.rules) { - for(let i = 0; i < rule.rules.length; i++) { + if (rule.rules) { + for (let i = 0; i < rule.rules.length; i++) { this._run(data, rule.rules[i], result); } } - if(rule.oneOf) { - for(let i = 0; i < rule.oneOf.length; i++) { - if(this._run(data, rule.oneOf[i], result)) - break; + if (rule.oneOf) { + for (let i = 0; i < rule.oneOf.length; i++) { + if (this._run(data, rule.oneOf[i], result)) break; } } @@ -437,7 +526,8 @@ module.exports = class RuleSet { findOptionsByIdent(ident) { const options = this.references[ident]; - if(!options) throw new Error("Can't find options with ident '" + ident + "'"); + if (!options) + throw new Error("Can't find options with ident '" + ident + "'"); return options; } }; diff --git a/lib/RuntimeTemplate.js b/lib/RuntimeTemplate.js index ac761bf9a..c229d364c 100644 --- a/lib/RuntimeTemplate.js +++ b/lib/RuntimeTemplate.js @@ -12,114 +12,97 @@ module.exports = class RuntimeTemplate { this.requestShortener = requestShortener; } - comment({ - request, - chunkName, - chunkReason, - message, - exportName - }) { + comment({ request, chunkName, chunkReason, message, exportName }) { let content; - if(this.outputOptions.pathinfo) { - content = [message, request, chunkName, chunkReason].filter(Boolean).map(item => this.requestShortener.shorten(item)).join(" | "); + if (this.outputOptions.pathinfo) { + content = [message, request, chunkName, chunkReason] + .filter(Boolean) + .map(item => this.requestShortener.shorten(item)) + .join(" | "); } else { - content = [message, chunkName, chunkReason].filter(Boolean).map(item => this.requestShortener.shorten(item)).join(" | "); + content = [message, chunkName, chunkReason] + .filter(Boolean) + .map(item => this.requestShortener.shorten(item)) + .join(" | "); } - if(!content) return ""; - if(this.outputOptions.pathinfo) { + if (!content) return ""; + if (this.outputOptions.pathinfo) { return Template.toComment(content) + " "; } else { return Template.toNormalComment(content) + " "; } } - throwMissingModuleErrorFunction({ - request - }) { + throwMissingModuleErrorFunction({ request }) { const err = `Cannot find module "${request}"`; - return `function webpackMissingModule() { var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND'; throw e; }`; + return `function webpackMissingModule() { var e = new Error(${JSON.stringify( + err + )}); e.code = 'MODULE_NOT_FOUND'; throw e; }`; } - missingModule({ - request - }) { + missingModule({ request }) { return `!(${this.throwMissingModuleErrorFunction({ request })}())`; } - missingModuleStatement({ - request - }) { + missingModuleStatement({ request }) { return `${this.missingModule({ request })};\n`; } - missingModulePromise({ - request - }) { - return `Promise.resolve().then(${this.throwMissingModuleErrorFunction({ request })})`; + missingModulePromise({ request }) { + return `Promise.resolve().then(${this.throwMissingModuleErrorFunction({ + request + })})`; } - moduleId({ - module, - request - }) { - if(!module) return this.missingModule({ - request - }); + moduleId({ module, request }) { + if (!module) + return this.missingModule({ + request + }); return `${this.comment({ request })}${JSON.stringify(module.id)}`; } - moduleRaw({ - module, - request - }) { - if(!module) return this.missingModule({ - request - }); + moduleRaw({ module, request }) { + if (!module) + return this.missingModule({ + request + }); return `__webpack_require__(${this.moduleId({ module, request })})`; } - moduleExports({ - module, - request - }) { + moduleExports({ module, request }) { return this.moduleRaw({ module, request }); } - moduleNamespace({ - module, - request, - strict - }) { + moduleNamespace({ module, request, strict }) { const rawModule = this.moduleRaw({ module, request }); const exportsType = module.buildMeta && module.buildMeta.exportsType; - if(exportsType === "namespace") { + if (exportsType === "namespace") { return rawModule; - } else if(exportsType === "named") { - return `Object.assign({/* fake namespace object */}, ${rawModule}, { "default": ${rawModule} })`; - } else if(strict) { + } else if (exportsType === "named") { + return `Object.assign({/* fake namespace object */}, ${ + rawModule + }, { "default": ${rawModule} })`; + } else if (strict) { return `Object({ /* fake namespace object */ "default": ${rawModule} })`; } else { - return `Object(function() { var module = ${rawModule}; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }())`; + return `Object(function() { var module = ${ + rawModule + }; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }())`; } } - moduleNamespacePromise({ - block, - module, - request, - message, - strict, - weak - }) { - if(!module) return this.missingModulePromise({ - request - }); + moduleNamespacePromise({ block, module, request, message, strict, weak }) { + if (!module) + return this.missingModulePromise({ + request + }); const promise = this.blockPromise({ block, message @@ -131,61 +114,81 @@ module.exports = class RuntimeTemplate { request }); let header = ""; - if(weak) { - if(idExpr.length > 8) { // 'var x="nnnnnn";x,"+x+",x' vs '"nnnnnn",nnnnnn,"nnnnnn"' + if (weak) { + if (idExpr.length > 8) { + // 'var x="nnnnnn";x,"+x+",x' vs '"nnnnnn",nnnnnn,"nnnnnn"' header += `var id = ${idExpr}; `; idExpr = "id"; } - header += `if(!__webpack_require__.m[${idExpr}]) { var e = new Error("Module '" + ${idExpr} + "' is not available (weak dependency)"); e.code = 'MODULE_NOT_FOUND'; throw e; } `; + header += `if(!__webpack_require__.m[${ + idExpr + }]) { var e = new Error("Module '" + ${ + idExpr + } + "' is not available (weak dependency)"); e.code = 'MODULE_NOT_FOUND'; throw e; } `; } const rawModule = this.moduleRaw({ module, request }); const exportsType = module.buildMeta && module.buildMeta.exportsType; - if(exportsType === "namespace") { - if(header) { + if (exportsType === "namespace") { + if (header) { getModuleFunction = `function() { ${header}return ${rawModule}; }`; } else { - getModuleFunction = `__webpack_require__.bind(null, ${comment}${idExpr})`; + getModuleFunction = `__webpack_require__.bind(null, ${comment}${ + idExpr + })`; } - } else if(exportsType === "named") { - getModuleFunction = `function() { ${header}var module = ${rawModule}; return Object.assign({/* fake namespace object */}, module, { "default": module }); }`; - } else if(strict) { - getModuleFunction = `function() { ${header}return { /* fake namespace object */ "default": ${rawModule} }; }`; + } else if (exportsType === "named") { + getModuleFunction = `function() { ${header}var module = ${ + rawModule + }; return Object.assign({/* fake namespace object */}, module, { "default": module }); }`; + } else if (strict) { + getModuleFunction = `function() { ${ + header + }return { /* fake namespace object */ "default": ${rawModule} }; }`; } else { - getModuleFunction = `function() { ${header}var module = ${rawModule}; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }`; + getModuleFunction = `function() { ${header}var module = ${ + rawModule + }; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }`; } return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`; } - importStatement({ - update, - module, - request, - importVar, - originModule - }) { - if(!module) return this.missingModuleStatement({ - request - }); + importStatement({ update, module, request, importVar, originModule }) { + if (!module) + return this.missingModuleStatement({ + request + }); const comment = this.comment({ request }); const optDeclaration = update ? "" : "var "; const exportsType = module.buildMeta && module.buildMeta.exportsType; - let content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${comment}${JSON.stringify(module.id)});\n`; + let content = `/* harmony import */ ${optDeclaration}${ + importVar + } = __webpack_require__(${comment}${JSON.stringify(module.id)});\n`; - if(!exportsType && !originModule.buildMeta.strictHarmonyModule) { - content += `/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/__webpack_require__.n(${importVar});\n`; + if (!exportsType && !originModule.buildMeta.strictHarmonyModule) { + content += `/* harmony import */ ${optDeclaration}${ + importVar + }_default = /*#__PURE__*/__webpack_require__.n(${importVar});\n`; } - if(exportsType === "named") { - if(Array.isArray(module.buildMeta.providedExports)) - content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/Object.assign({}, ${importVar}, {"default": ${importVar}});\n`; + if (exportsType === "named") { + if (Array.isArray(module.buildMeta.providedExports)) + content += `${optDeclaration}${ + importVar + }_namespace = /*#__PURE__*/Object.assign({}, ${ + importVar + }, {"default": ${importVar}});\n`; else - content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/{ /* fake namespace object */ "default": ${importVar} };\n`; + content += `${optDeclaration}${ + importVar + }_namespace = /*#__PURE__*/{ /* fake namespace object */ "default": ${ + importVar + } };\n`; } return content; } @@ -200,53 +203,54 @@ module.exports = class RuntimeTemplate { callContext, importVar }) { - if(!module) return this.missingModule({ - request - }); + if (!module) + return this.missingModule({ + request + }); const exportsType = module.buildMeta && module.buildMeta.exportsType; - if(!exportsType) { - if(exportName === "default") { - if(!originModule.buildMeta.strictHarmonyModule) { - if(isCall) - return `${importVar}_default()`; - else if(asiSafe) - return `(${importVar}_default())`; - else - return `${importVar}_default.a`; + if (!exportsType) { + if (exportName === "default") { + if (!originModule.buildMeta.strictHarmonyModule) { + if (isCall) return `${importVar}_default()`; + else if (asiSafe) return `(${importVar}_default())`; + else return `${importVar}_default.a`; } else { return importVar; } - } else if(originModule.buildMeta.strictHarmonyModule) { - if(exportName) { + } else if (originModule.buildMeta.strictHarmonyModule) { + if (exportName) { return "/* non-default import from non-esm module */undefined"; - } else if(!exportName) { - if(asiSafe) { - return `/*#__PURE__*/{ /* fake namespace object */ "default": ${importVar} }`; + } else if (!exportName) { + if (asiSafe) { + return `/*#__PURE__*/{ /* fake namespace object */ "default": ${ + importVar + } }`; } else { - return `/*#__PURE__*/Object({ /* fake namespace object */ "default": ${importVar} })`; + return `/*#__PURE__*/Object({ /* fake namespace object */ "default": ${ + importVar + } })`; } } } } - if(exportsType === "named") { - if(exportName === "default") { + if (exportsType === "named") { + if (exportName === "default") { return importVar; - } else if(!exportName) { + } else if (!exportName) { return `${importVar}_namespace`; } } - if(exportName) { + if (exportName) { const used = module.isUsed(exportName); - const comment = used !== exportName ? Template.toNormalComment(exportName) + " " : ""; + const comment = + used !== exportName ? Template.toNormalComment(exportName) + " " : ""; const access = `${importVar}[${comment}${JSON.stringify(used)}]`; - if(isCall) { - if(callContext === false && asiSafe) - return `(0,${access})`; - else if(callContext === false) - return `Object(${access})`; + if (isCall) { + if (callContext === false && asiSafe) return `(0,${access})`; + else if (callContext === false) return `Object(${access})`; } return access; } else { @@ -254,28 +258,30 @@ module.exports = class RuntimeTemplate { } } - blockPromise({ - block, - message - }) { - if(!block || !block.chunkGroup || block.chunkGroup.chunks.length === 0) { + blockPromise({ block, message }) { + if (!block || !block.chunkGroup || block.chunkGroup.chunks.length === 0) { const comment = this.comment({ message }); return `Promise.resolve(${comment.trim()})`; } - const chunks = block.chunkGroup.chunks.filter(chunk => !chunk.hasRuntime() && chunk.id !== null); + const chunks = block.chunkGroup.chunks.filter( + chunk => !chunk.hasRuntime() && chunk.id !== null + ); const comment = this.comment({ message, chunkName: block.chunkName, chunkReason: block.chunkReason }); - if(chunks.length === 1) { + if (chunks.length === 1) { const chunkId = JSON.stringify(chunks[0].id); return `__webpack_require__.e(${comment}${chunkId})`; - } else if(chunks.length > 0) { - const requireChunkId = chunk => `__webpack_require__.e(${JSON.stringify(chunk.id)})`; - return `Promise.all(${comment.trim()}[${chunks.map(requireChunkId).join(", ")}])`; + } else if (chunks.length > 0) { + const requireChunkId = chunk => + `__webpack_require__.e(${JSON.stringify(chunk.id)})`; + return `Promise.all(${comment.trim()}[${chunks + .map(requireChunkId) + .join(", ")}])`; } else { return `Promise.resolve(${comment.trim()})`; } @@ -285,9 +291,7 @@ module.exports = class RuntimeTemplate { return "__webpack_require__.oe"; } - defineEsModuleFlagStatement({ - exportsArgument - }) { + defineEsModuleFlagStatement({ exportsArgument }) { return `__webpack_require__.r(${exportsArgument});\n`; } }; diff --git a/lib/SetVarMainTemplatePlugin.js b/lib/SetVarMainTemplatePlugin.js index 4a25f399a..414881e67 100644 --- a/lib/SetVarMainTemplatePlugin.js +++ b/lib/SetVarMainTemplatePlugin.js @@ -13,32 +13,39 @@ class SetVarMainTemplatePlugin { } apply(compilation) { - const { - mainTemplate, - chunkTemplate - } = compilation; + const { mainTemplate, chunkTemplate } = compilation; const onRenderWithEntry = (source, chunk, hash) => { const varExpression = mainTemplate.getAssetPath(this.varExpression, { hash, chunk }); - if(this.copyObject) { - return new ConcatSource(`(function(e, a) { for(var i in a) e[i] = a[i]; }(${varExpression}, `, source, "))"); + if (this.copyObject) { + return new ConcatSource( + `(function(e, a) { for(var i in a) e[i] = a[i]; }(${varExpression}, `, + source, + "))" + ); } else { const prefix = `${varExpression} =\n`; return new ConcatSource(prefix, source); } }; - for(const template of [mainTemplate, chunkTemplate]) { - template.hooks.renderWithEntry.tap("SetVarMainTemplatePlugin", onRenderWithEntry); + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "SetVarMainTemplatePlugin", + onRenderWithEntry + ); } - mainTemplate.hooks.globalHashPaths.tap("SetVarMainTemplatePlugin", paths => { - if(this.varExpression) paths.push(this.varExpression); - return paths; - }); + mainTemplate.hooks.globalHashPaths.tap( + "SetVarMainTemplatePlugin", + paths => { + if (this.varExpression) paths.push(this.varExpression); + return paths; + } + ); mainTemplate.hooks.hash.tap("SetVarMainTemplatePlugin", hash => { hash.update("set var"); hash.update(`${this.varExpression}`); diff --git a/lib/SingleEntryPlugin.js b/lib/SingleEntryPlugin.js index 389526190..755a6b597 100644 --- a/lib/SingleEntryPlugin.js +++ b/lib/SingleEntryPlugin.js @@ -13,22 +13,25 @@ class SingleEntryPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("SingleEntryPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); + compiler.hooks.compilation.tap( + "SingleEntryPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); - compiler.hooks.make.tapAsync("SingleEntryPlugin", (compilation, callback) => { - const { - entry, - name, - context - } = this; + compiler.hooks.make.tapAsync( + "SingleEntryPlugin", + (compilation, callback) => { + const { entry, name, context } = this; - const dep = SingleEntryPlugin.createDependency(entry, name); - compilation.addEntry(context, dep, name, callback); - }); + const dep = SingleEntryPlugin.createDependency(entry, name); + compilation.addEntry(context, dep, name, callback); + } + ); } static createDependency(entry, name) { diff --git a/lib/SizeFormatHelpers.js b/lib/SizeFormatHelpers.js index aaa517e5e..85bbd2c02 100644 --- a/lib/SizeFormatHelpers.js +++ b/lib/SizeFormatHelpers.js @@ -7,12 +7,14 @@ const SizeFormatHelpers = exports; SizeFormatHelpers.formatSize = size => { - if(size <= 0) { + if (size <= 0) { return "0 bytes"; } const abbreviations = ["bytes", "KiB", "MiB", "GiB"]; const index = Math.floor(Math.log(size) / Math.log(1024)); - return `${+(size / Math.pow(1024, index)).toPrecision(3)} ${abbreviations[index]}`; + return `${+(size / Math.pow(1024, index)).toPrecision(3)} ${ + abbreviations[index] + }`; }; diff --git a/lib/SourceMapDevToolModuleOptionsPlugin.js b/lib/SourceMapDevToolModuleOptionsPlugin.js index 916989b2a..e593ced7b 100644 --- a/lib/SourceMapDevToolModuleOptionsPlugin.js +++ b/lib/SourceMapDevToolModuleOptionsPlugin.js @@ -13,23 +13,35 @@ class SourceMapDevToolModuleOptionsPlugin { apply(compilation) { const options = this.options; - if(options.module !== false) { - compilation.hooks.buildModule.tap("SourceMapDevToolModuleOptionsPlugin", module => { - module.useSourceMap = true; - }); + if (options.module !== false) { + compilation.hooks.buildModule.tap( + "SourceMapDevToolModuleOptionsPlugin", + module => { + module.useSourceMap = true; + } + ); } - if(options.lineToLine === true) { - compilation.hooks.buildModule.tap("SourceMapDevToolModuleOptionsPlugin", module => { - module.lineToLine = true; - }); - } else if(options.lineToLine) { - compilation.hooks.buildModule.tap("SourceMapDevToolModuleOptionsPlugin", module => { - if(!module.resource) return; - let resourcePath = module.resource; - const idx = resourcePath.indexOf("?"); - if(idx >= 0) resourcePath = resourcePath.substr(0, idx); - module.lineToLine = ModuleFilenameHelpers.matchObject(options.lineToLine, resourcePath); - }); + if (options.lineToLine === true) { + compilation.hooks.buildModule.tap( + "SourceMapDevToolModuleOptionsPlugin", + module => { + module.lineToLine = true; + } + ); + } else if (options.lineToLine) { + compilation.hooks.buildModule.tap( + "SourceMapDevToolModuleOptionsPlugin", + module => { + if (!module.resource) return; + let resourcePath = module.resource; + const idx = resourcePath.indexOf("?"); + if (idx >= 0) resourcePath = resourcePath.substr(0, idx); + module.lineToLine = ModuleFilenameHelpers.matchObject( + options.lineToLine, + resourcePath + ); + } + ); } } } diff --git a/lib/SourceMapDevToolPlugin.js b/lib/SourceMapDevToolPlugin.js index e729dce55..e57938668 100644 --- a/lib/SourceMapDevToolPlugin.js +++ b/lib/SourceMapDevToolPlugin.js @@ -14,24 +14,23 @@ const createHash = require("./util/createHash"); const validateOptions = require("schema-utils"); const schema = require("../schemas/plugins/SourceMapDevToolPlugin.json"); -const basename = (name) => { - if(!name.includes("/")) return name; +const basename = name => { + if (!name.includes("/")) return name; return name.substr(name.lastIndexOf("/") + 1); }; const getTaskForFile = (file, chunk, options, compilation) => { const asset = compilation.assets[file]; - if(asset.__SourceMapDevToolFile === file && asset.__SourceMapDevToolData) { + if (asset.__SourceMapDevToolFile === file && asset.__SourceMapDevToolData) { const data = asset.__SourceMapDevToolData; - for(const cachedFile in data) { + for (const cachedFile in data) { compilation.assets[cachedFile] = data[cachedFile]; - if(cachedFile !== file) - chunk.files.push(cachedFile); + if (cachedFile !== file) chunk.files.push(cachedFile); } return; } let source, sourceMap; - if(asset.sourceAndMap) { + if (asset.sourceAndMap) { const sourceAndMap = asset.sourceAndMap(options); sourceMap = sourceAndMap.map; source = sourceAndMap.source; @@ -39,7 +38,7 @@ const getTaskForFile = (file, chunk, options, compilation) => { sourceMap = asset.map(options); source = asset.source(); } - if(sourceMap) { + if (sourceMap) { return { chunk, file, @@ -53,16 +52,24 @@ const getTaskForFile = (file, chunk, options, compilation) => { class SourceMapDevToolPlugin { constructor(options) { - if(arguments.length > 1) - throw new Error("SourceMapDevToolPlugin only takes one argument (pass an options object)"); + if (arguments.length > 1) + throw new Error( + "SourceMapDevToolPlugin only takes one argument (pass an options object)" + ); validateOptions(schema, options || {}, "SourceMap DevTool Plugin"); - if(!options) options = {}; + if (!options) options = {}; this.sourceMapFilename = options.filename; - this.sourceMappingURLComment = options.append === false ? false : options.append || "\n//# sourceMappingURL=[url]"; - this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]"; - this.fallbackModuleFilenameTemplate = options.fallbackModuleFilenameTemplate || "webpack://[namespace]/[resourcePath]?[hash]"; + this.sourceMappingURLComment = + options.append === false + ? false + : options.append || "\n//# sourceMappingURL=[url]"; + this.moduleFilenameTemplate = + options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]"; + this.fallbackModuleFilenameTemplate = + options.fallbackModuleFilenameTemplate || + "webpack://[namespace]/[resourcePath]?[hash]"; this.namespace = options.namespace || ""; this.options = options; } @@ -77,157 +84,223 @@ class SourceMapDevToolPlugin { const options = this.options; options.test = options.test || /\.(js|css)($|\?)/i; - const matchObject = ModuleFilenameHelpers.matchObject.bind(undefined, options); + const matchObject = ModuleFilenameHelpers.matchObject.bind( + undefined, + options + ); - compiler.hooks.compilation.tap("SourceMapDevToolPlugin", (compilation) => { + compiler.hooks.compilation.tap("SourceMapDevToolPlugin", compilation => { new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); - compilation.hooks.afterOptimizeChunkAssets.tap({ - name: "SourceMapDevToolPlugin", - context: true - }, (context, chunks) => { - const moduleToSourceNameMapping = new Map(); - const reportProgress = (context && context.reportProgress) ? context.reportProgress : () => {}; + compilation.hooks.afterOptimizeChunkAssets.tap( + { + name: "SourceMapDevToolPlugin", + context: true + }, + (context, chunks) => { + const moduleToSourceNameMapping = new Map(); + const reportProgress = + context && context.reportProgress + ? context.reportProgress + : () => {}; - const files = []; - for(const chunk of chunks) { - for(const file of chunk.files) { - if(matchObject(file)) { - files.push({ - file, - chunk - }); - } - } - } - - reportProgress(0.0); - const tasks = []; - files.forEach(({ - file, - chunk - }, idx) => { - reportProgress(0.5 * idx / files.length, file, "generate SourceMap"); - const task = getTaskForFile(file, chunk, options, compilation); - - if(task) { - const modules = task.sourceMap.sources.map(source => { - const module = compilation.findModule(source); - return module || source; - }); - - for(let idx = 0; idx < modules.length; idx++) { - const module = modules[idx]; - if(!moduleToSourceNameMapping.get(module)) { - moduleToSourceNameMapping.set(module, ModuleFilenameHelpers.createFilename(module, { - moduleFilenameTemplate: moduleFilenameTemplate, - namespace: namespace - }, requestShortener)); + const files = []; + for (const chunk of chunks) { + for (const file of chunk.files) { + if (matchObject(file)) { + files.push({ + file, + chunk + }); } } - - task.modules = modules; - - tasks.push(task); } - }); + reportProgress(0.0); + const tasks = []; + files.forEach(({ file, chunk }, idx) => { + reportProgress( + 0.5 * idx / files.length, + file, + "generate SourceMap" + ); + const task = getTaskForFile(file, chunk, options, compilation); - reportProgress(0.5, "resolve sources"); - const usedNamesSet = new Set(moduleToSourceNameMapping.values()); - const conflictDetectionSet = new Set(); + if (task) { + const modules = task.sourceMap.sources.map(source => { + const module = compilation.findModule(source); + return module || source; + }); - // all modules in defined order (longest identifier first) - const allModules = Array.from(moduleToSourceNameMapping.keys()).sort((a, b) => { - const ai = typeof a === "string" ? a : a.identifier(); - const bi = typeof b === "string" ? b : b.identifier(); - return ai.length - bi.length; - }); + for (let idx = 0; idx < modules.length; idx++) { + const module = modules[idx]; + if (!moduleToSourceNameMapping.get(module)) { + moduleToSourceNameMapping.set( + module, + ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: moduleFilenameTemplate, + namespace: namespace + }, + requestShortener + ) + ); + } + } - // find modules with conflicting source names - for(let idx = 0; idx < allModules.length; idx++) { - const module = allModules[idx]; - let sourceName = moduleToSourceNameMapping.get(module); - let hasName = conflictDetectionSet.has(sourceName); - if(!hasName) { - conflictDetectionSet.add(sourceName); - continue; - } + task.modules = modules; - // try the fallback name first - sourceName = ModuleFilenameHelpers.createFilename(module, { - moduleFilenameTemplate: fallbackModuleFilenameTemplate, - namespace: namespace - }, requestShortener); - hasName = usedNamesSet.has(sourceName); - if(!hasName) { + tasks.push(task); + } + }); + + reportProgress(0.5, "resolve sources"); + const usedNamesSet = new Set(moduleToSourceNameMapping.values()); + const conflictDetectionSet = new Set(); + + // all modules in defined order (longest identifier first) + const allModules = Array.from(moduleToSourceNameMapping.keys()).sort( + (a, b) => { + const ai = typeof a === "string" ? a : a.identifier(); + const bi = typeof b === "string" ? b : b.identifier(); + return ai.length - bi.length; + } + ); + + // find modules with conflicting source names + for (let idx = 0; idx < allModules.length; idx++) { + const module = allModules[idx]; + let sourceName = moduleToSourceNameMapping.get(module); + let hasName = conflictDetectionSet.has(sourceName); + if (!hasName) { + conflictDetectionSet.add(sourceName); + continue; + } + + // try the fallback name first + sourceName = ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: fallbackModuleFilenameTemplate, + namespace: namespace + }, + requestShortener + ); + hasName = usedNamesSet.has(sourceName); + if (!hasName) { + moduleToSourceNameMapping.set(module, sourceName); + usedNamesSet.add(sourceName); + continue; + } + + // elsewise just append stars until we have a valid name + while (hasName) { + sourceName += "*"; + hasName = usedNamesSet.has(sourceName); + } moduleToSourceNameMapping.set(module, sourceName); usedNamesSet.add(sourceName); - continue; } - - // elsewise just append stars until we have a valid name - while(hasName) { - sourceName += "*"; - hasName = usedNamesSet.has(sourceName); - } - moduleToSourceNameMapping.set(module, sourceName); - usedNamesSet.add(sourceName); - } - tasks.forEach((task, index) => { - reportProgress(0.5 + 0.5 * index / tasks.length, task.file, "attach SourceMap"); - const chunk = task.chunk; - const file = task.file; - const asset = task.asset; - const sourceMap = task.sourceMap; - const source = task.source; - const modules = task.modules; - const moduleFilenames = modules.map(m => moduleToSourceNameMapping.get(m)); - sourceMap.sources = moduleFilenames; - if(options.noSources) { - sourceMap.sourcesContent = undefined; - } - sourceMap.sourceRoot = options.sourceRoot || ""; - sourceMap.file = file; - asset.__SourceMapDevToolFile = file; - asset.__SourceMapDevToolData = {}; - let currentSourceMappingURLComment = sourceMappingURLComment; - if(currentSourceMappingURLComment !== false && /\.css($|\?)/i.test(file)) { - currentSourceMappingURLComment = currentSourceMappingURLComment.replace(/^\n\/\/(.*)$/, "\n/*$1*/"); - } - const sourceMapString = JSON.stringify(sourceMap); - if(sourceMapFilename) { - let filename = file; - let query = ""; - const idx = filename.indexOf("?"); - if(idx >= 0) { - query = filename.substr(idx); - filename = filename.substr(0, idx); - } - let sourceMapFile = compilation.getPath(sourceMapFilename, { - chunk, - filename: options.fileContext ? path.relative(options.fileContext, filename) : filename, - query, - basename: basename(filename) - }); - if(sourceMapFile.includes("[contenthash]")) { - sourceMapFile = sourceMapFile.replace(/\[contenthash\]/g, createHash("md4").update(sourceMapString).digest("hex")); - } - const sourceMapUrl = options.publicPath ? options.publicPath + sourceMapFile.replace(/\\/g, "/") : path.relative(path.dirname(file), sourceMapFile).replace(/\\/g, "/"); - if(currentSourceMappingURLComment !== false) { - asset.__SourceMapDevToolData[file] = compilation.assets[file] = new ConcatSource(new RawSource(source), currentSourceMappingURLComment.replace(/\[url\]/g, sourceMapUrl)); - } - asset.__SourceMapDevToolData[sourceMapFile] = compilation.assets[sourceMapFile] = new RawSource(sourceMapString); - chunk.files.push(sourceMapFile); - } else { - asset.__SourceMapDevToolData[file] = compilation.assets[file] = new ConcatSource(new RawSource(source), currentSourceMappingURLComment - .replace(/\[map\]/g, () => sourceMapString) - .replace(/\[url\]/g, () => `data:application/json;charset=utf-8;base64,${Buffer.from(sourceMapString, "utf-8").toString("base64")}`) + tasks.forEach((task, index) => { + reportProgress( + 0.5 + 0.5 * index / tasks.length, + task.file, + "attach SourceMap" ); - } - }); - reportProgress(1.0); - }); + const chunk = task.chunk; + const file = task.file; + const asset = task.asset; + const sourceMap = task.sourceMap; + const source = task.source; + const modules = task.modules; + const moduleFilenames = modules.map(m => + moduleToSourceNameMapping.get(m) + ); + sourceMap.sources = moduleFilenames; + if (options.noSources) { + sourceMap.sourcesContent = undefined; + } + sourceMap.sourceRoot = options.sourceRoot || ""; + sourceMap.file = file; + asset.__SourceMapDevToolFile = file; + asset.__SourceMapDevToolData = {}; + let currentSourceMappingURLComment = sourceMappingURLComment; + if ( + currentSourceMappingURLComment !== false && + /\.css($|\?)/i.test(file) + ) { + currentSourceMappingURLComment = currentSourceMappingURLComment.replace( + /^\n\/\/(.*)$/, + "\n/*$1*/" + ); + } + const sourceMapString = JSON.stringify(sourceMap); + if (sourceMapFilename) { + let filename = file; + let query = ""; + const idx = filename.indexOf("?"); + if (idx >= 0) { + query = filename.substr(idx); + filename = filename.substr(0, idx); + } + let sourceMapFile = compilation.getPath(sourceMapFilename, { + chunk, + filename: options.fileContext + ? path.relative(options.fileContext, filename) + : filename, + query, + basename: basename(filename) + }); + if (sourceMapFile.includes("[contenthash]")) { + sourceMapFile = sourceMapFile.replace( + /\[contenthash\]/g, + createHash("md4") + .update(sourceMapString) + .digest("hex") + ); + } + const sourceMapUrl = options.publicPath + ? options.publicPath + sourceMapFile.replace(/\\/g, "/") + : path + .relative(path.dirname(file), sourceMapFile) + .replace(/\\/g, "/"); + if (currentSourceMappingURLComment !== false) { + asset.__SourceMapDevToolData[file] = compilation.assets[ + file + ] = new ConcatSource( + new RawSource(source), + currentSourceMappingURLComment.replace( + /\[url\]/g, + sourceMapUrl + ) + ); + } + asset.__SourceMapDevToolData[sourceMapFile] = compilation.assets[ + sourceMapFile + ] = new RawSource(sourceMapString); + chunk.files.push(sourceMapFile); + } else { + asset.__SourceMapDevToolData[file] = compilation.assets[ + file + ] = new ConcatSource( + new RawSource(source), + currentSourceMappingURLComment + .replace(/\[map\]/g, () => sourceMapString) + .replace( + /\[url\]/g, + () => + `data:application/json;charset=utf-8;base64,${Buffer.from( + sourceMapString, + "utf-8" + ).toString("base64")}` + ) + ); + } + }); + reportProgress(1.0); + } + ); }); } } diff --git a/lib/Stats.js b/lib/Stats.js index 0347250e7..4b4ccc3d0 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -23,26 +23,28 @@ class Stats { static filterWarnings(warnings, warningsFilter) { // we dont have anything to filter so all warnings can be shown - if(!warningsFilter) { + if (!warningsFilter) { return warnings; } // create a chain of filters // if they return "true" a warning should be surpressed const normalizedWarningsFilters = [].concat(warningsFilter).map(filter => { - if(typeof filter === "string") { + if (typeof filter === "string") { return warning => warning.includes(filter); } - if(filter instanceof RegExp) { + if (filter instanceof RegExp) { return warning => filter.test(warning); } - if(typeof filter === "function") { + if (typeof filter === "function") { return filter; } - throw new Error(`Can only filter warnings with Strings or RegExps. (Given: ${filter})`); + throw new Error( + `Can only filter warnings with Strings or RegExps. (Given: ${filter})` + ); }); return warnings.filter(warning => { return !normalizedWarningsFilters.some(check => check(warning)); @@ -50,18 +52,22 @@ class Stats { } hasWarnings() { - return this.compilation.warnings.length > 0 || - this.compilation.children.some(child => child.getStats().hasWarnings()); + return ( + this.compilation.warnings.length > 0 || + this.compilation.children.some(child => child.getStats().hasWarnings()) + ); } hasErrors() { - return this.compilation.errors.length > 0 || - this.compilation.children.some(child => child.getStats().hasErrors()); + return ( + this.compilation.errors.length > 0 || + this.compilation.children.some(child => child.getStats().hasErrors()) + ); } // remove a prefixed "!" that can be specified to reverse sort order normalizeFieldKey(field) { - if(field[0] === "!") { + if (field[0] === "!") { return field.substr(1); } return field; @@ -69,37 +75,48 @@ class Stats { // if a field is prefixed by a "!" reverse sort order sortOrderRegular(field) { - if(field[0] === "!") { + if (field[0] === "!") { return false; } return true; } toJson(options, forToString) { - if(typeof options === "boolean" || typeof options === "string") { + if (typeof options === "boolean" || typeof options === "string") { options = Stats.presetToOptions(options); - } else if(!options) { + } else if (!options) { options = {}; } const optionOrLocalFallback = (v, def) => - typeof v !== "undefined" ? v : - typeof options.all !== "undefined" ? options.all : def; + typeof v !== "undefined" + ? v + : typeof options.all !== "undefined" ? options.all : def; - const testAgainstGivenOption = (item) => { - if(typeof item === "string") { - const regExp = new RegExp(`[\\\\/]${item.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")}([\\\\/]|$|!|\\?)`); // eslint-disable-line no-useless-escape + const testAgainstGivenOption = item => { + if (typeof item === "string") { + const regExp = new RegExp( + `[\\\\/]${item.replace( + /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, + "\\$&" + )}([\\\\/]|$|!|\\?)` + ); // eslint-disable-line no-useless-escape return ident => regExp.test(ident); } - if(item && typeof item === "object" && typeof item.test === "function") + if (item && typeof item === "object" && typeof item.test === "function") return ident => item.test(ident); - if(typeof item === "function") - return item; + if (typeof item === "function") return item; }; const compilation = this.compilation; - const context = optionsOrFallback(options.context, compilation.compiler.context); - const requestShortener = compilation.compiler.context === context ? compilation.requestShortener : new RequestShortener(context); + const context = optionsOrFallback( + options.context, + compilation.compiler.context + ); + const requestShortener = + compilation.compiler.context === context + ? compilation.requestShortener + : new RequestShortener(context); const showPerformance = optionOrLocalFallback(options.performance, true); const showHash = optionOrLocalFallback(options.hash, true); const showEnv = optionOrLocalFallback(options.env, false); @@ -110,44 +127,74 @@ class Stats { const showEntrypoints = optionOrLocalFallback(options.entrypoints, true); const showChunks = optionOrLocalFallback(options.chunks, !forToString); const showChunkModules = optionOrLocalFallback(options.chunkModules, true); - const showChunkOrigins = optionOrLocalFallback(options.chunkOrigins, !forToString); + const showChunkOrigins = optionOrLocalFallback( + options.chunkOrigins, + !forToString + ); const showModules = optionOrLocalFallback(options.modules, true); - const showNestedModules = optionOrLocalFallback(options.nestedModules, true); + const showNestedModules = optionOrLocalFallback( + options.nestedModules, + true + ); const showDepth = optionOrLocalFallback(options.depth, !forToString); const showCachedModules = optionOrLocalFallback(options.cached, true); const showCachedAssets = optionOrLocalFallback(options.cachedAssets, true); const showReasons = optionOrLocalFallback(options.reasons, !forToString); - const showUsedExports = optionOrLocalFallback(options.usedExports, !forToString); - const showProvidedExports = optionOrLocalFallback(options.providedExports, !forToString); - const showOptimizationBailout = optionOrLocalFallback(options.optimizationBailout, !forToString); + const showUsedExports = optionOrLocalFallback( + options.usedExports, + !forToString + ); + const showProvidedExports = optionOrLocalFallback( + options.providedExports, + !forToString + ); + const showOptimizationBailout = optionOrLocalFallback( + options.optimizationBailout, + !forToString + ); const showChildren = optionOrLocalFallback(options.children, true); const showSource = optionOrLocalFallback(options.source, !forToString); const showModuleTrace = optionOrLocalFallback(options.moduleTrace, true); const showErrors = optionOrLocalFallback(options.errors, true); - const showErrorDetails = optionOrLocalFallback(options.errorDetails, !forToString); + const showErrorDetails = optionOrLocalFallback( + options.errorDetails, + !forToString + ); const showWarnings = optionOrLocalFallback(options.warnings, true); const warningsFilter = optionsOrFallback(options.warningsFilter, null); - const showPublicPath = optionOrLocalFallback(options.publicPath, !forToString); - const excludeModules = [].concat(optionsOrFallback(options.excludeModules, options.exclude, [])).map(testAgainstGivenOption); - const excludeAssets = [].concat(optionsOrFallback(options.excludeAssets, [])).map(testAgainstGivenOption); - const maxModules = optionsOrFallback(options.maxModules, forToString ? 15 : Infinity); + const showPublicPath = optionOrLocalFallback( + options.publicPath, + !forToString + ); + const excludeModules = [] + .concat(optionsOrFallback(options.excludeModules, options.exclude, [])) + .map(testAgainstGivenOption); + const excludeAssets = [] + .concat(optionsOrFallback(options.excludeAssets, [])) + .map(testAgainstGivenOption); + const maxModules = optionsOrFallback( + options.maxModules, + forToString ? 15 : Infinity + ); const sortModules = optionsOrFallback(options.modulesSort, "id"); const sortChunks = optionsOrFallback(options.chunksSort, "id"); const sortAssets = optionsOrFallback(options.assetsSort, ""); - const showOutputPath = optionOrLocalFallback(options.outputPath, !forToString); + const showOutputPath = optionOrLocalFallback( + options.outputPath, + !forToString + ); - if(!showCachedModules) { + if (!showCachedModules) { excludeModules.push((ident, module) => !module.built); } const createModuleFilter = () => { let i = 0; return module => { - if(excludeModules.length > 0) { + if (excludeModules.length > 0) { const ident = requestShortener.shorten(module.resource); const excluded = excludeModules.some(fn => fn(ident, module)); - if(excluded) - return false; + if (excluded) return false; } const result = i < maxModules; i++; @@ -157,26 +204,25 @@ class Stats { const createAssetFilter = () => { return asset => { - if(excludeAssets.length > 0) { + if (excludeAssets.length > 0) { const ident = asset.name; const excluded = excludeAssets.some(fn => fn(ident, asset)); - if(excluded) - return false; + if (excluded) return false; } return showCachedAssets || asset.emitted; }; }; const sortByFieldAndOrder = (fieldKey, a, b) => { - if(a[fieldKey] === null && b[fieldKey] === null) return 0; - if(a[fieldKey] === null) return 1; - if(b[fieldKey] === null) return -1; - if(a[fieldKey] === b[fieldKey]) return 0; + if (a[fieldKey] === null && b[fieldKey] === null) return 0; + if (a[fieldKey] === null) return 1; + if (b[fieldKey] === null) return -1; + if (a[fieldKey] === b[fieldKey]) return 0; return a[fieldKey] < b[fieldKey] ? -1 : 1; }; - const sortByField = (field) => (a, b) => { - if(!field) { + const sortByField = field => (a, b) => { + if (!field) { return 0; } @@ -185,45 +231,57 @@ class Stats { // if a field is prefixed with a "!" the sort is reversed! const sortIsRegular = this.sortOrderRegular(field); - return sortByFieldAndOrder(fieldKey, sortIsRegular ? a : b, sortIsRegular ? b : a); + return sortByFieldAndOrder( + fieldKey, + sortIsRegular ? a : b, + sortIsRegular ? b : a + ); }; - const formatError = (e) => { + const formatError = e => { let text = ""; - if(typeof e === "string") + if (typeof e === "string") e = { message: e }; - if(e.chunk) { - text += `chunk ${e.chunk.name || e.chunk.id}${e.chunk.hasRuntime() ? " [entry]" : e.chunk.canBeInitial() ? " [initial]" : ""}\n`; + if (e.chunk) { + text += `chunk ${e.chunk.name || e.chunk.id}${ + e.chunk.hasRuntime() + ? " [entry]" + : e.chunk.canBeInitial() ? " [initial]" : "" + }\n`; } - if(e.file) { + if (e.file) { text += `${e.file}\n`; } - if(e.module && e.module.readableIdentifier && typeof e.module.readableIdentifier === "function") { + if ( + e.module && + e.module.readableIdentifier && + typeof e.module.readableIdentifier === "function" + ) { text += `${e.module.readableIdentifier(requestShortener)}\n`; } text += e.message; - if(showErrorDetails && e.details) text += `\n${e.details}`; - if(showErrorDetails && e.missing) text += e.missing.map(item => `\n[${item}]`).join(""); - if(showModuleTrace && e.origin) { + if (showErrorDetails && e.details) text += `\n${e.details}`; + if (showErrorDetails && e.missing) + text += e.missing.map(item => `\n[${item}]`).join(""); + if (showModuleTrace && e.origin) { text += `\n @ ${e.origin.readableIdentifier(requestShortener)}`; - if(typeof e.originLoc === "object") { + if (typeof e.originLoc === "object") { const locInfo = formatLocation(e.originLoc); - if(locInfo) - text += ` ${locInfo}`; + if (locInfo) text += ` ${locInfo}`; } - if(e.dependencies) { - for(const dep of e.dependencies) { - if(!dep.loc) continue; - if(typeof dep.loc === "string") continue; + if (e.dependencies) { + for (const dep of e.dependencies) { + if (!dep.loc) continue; + if (typeof dep.loc === "string") continue; const locInfo = formatLocation(dep.loc); - if(!locInfo) continue; + if (!locInfo) continue; text += ` ${locInfo}`; } } let current = e.origin; - while(current.issuer) { + while (current.issuer) { current = current.issuer; text += `\n @ ${current.readableIdentifier(requestShortener)}`; } @@ -233,7 +291,10 @@ class Stats { const obj = { errors: compilation.errors.map(formatError), - warnings: Stats.filterWarnings(compilation.warnings.map(formatError), warningsFilter) + warnings: Stats.filterWarnings( + compilation.warnings.map(formatError), + warningsFilter + ) }; //We just hint other renderers since actually omitting @@ -247,68 +308,71 @@ class Stats { enumerable: false }); - if(showVersion) { + if (showVersion) { obj.version = require("../package.json").version; } - if(showHash) obj.hash = this.hash; - if(showTimings && this.startTime && this.endTime) { + if (showHash) obj.hash = this.hash; + if (showTimings && this.startTime && this.endTime) { obj.time = this.endTime - this.startTime; } - if(showBuiltAt && this.endTime) { + if (showBuiltAt && this.endTime) { obj.builtAt = this.endTime; } - if(showEnv && options._env) { + if (showEnv && options._env) { obj.env = options._env; } - if(compilation.needAdditionalPass) { + if (compilation.needAdditionalPass) { obj.needAdditionalPass = true; } - if(showPublicPath) { + if (showPublicPath) { obj.publicPath = this.compilation.mainTemplate.getPublicPath({ hash: this.compilation.hash }); } - if(showOutputPath) { + if (showOutputPath) { obj.outputPath = this.compilation.mainTemplate.outputOptions.path; } - if(showAssets) { + if (showAssets) { const assetsByFile = {}; const compilationAssets = Object.keys(compilation.assets); obj.assetsByChunkName = {}; - obj.assets = compilationAssets.map(asset => { - const obj = { - name: asset, - size: compilation.assets[asset].size(), - chunks: [], - chunkNames: [], - emitted: compilation.assets[asset].emitted - }; + obj.assets = compilationAssets + .map(asset => { + const obj = { + name: asset, + size: compilation.assets[asset].size(), + chunks: [], + chunkNames: [], + emitted: compilation.assets[asset].emitted + }; - if(showPerformance) { - obj.isOverSizeLimit = compilation.assets[asset].isOverSizeLimit; - } + if (showPerformance) { + obj.isOverSizeLimit = compilation.assets[asset].isOverSizeLimit; + } - assetsByFile[asset] = obj; - return obj; - }).filter(createAssetFilter()); + assetsByFile[asset] = obj; + return obj; + }) + .filter(createAssetFilter()); obj.filteredAssets = compilationAssets.length - obj.assets.length; - for(const chunk of compilation.chunks) { - for(const asset of chunk.files) { - if(assetsByFile[asset]) { - for(const id of chunk.ids) { + for (const chunk of compilation.chunks) { + for (const asset of chunk.files) { + if (assetsByFile[asset]) { + for (const id of chunk.ids) { assetsByFile[asset].chunks.push(id); } - if(chunk.name) { + if (chunk.name) { assetsByFile[asset].chunkNames.push(chunk.name); - if(obj.assetsByChunkName[chunk.name]) - obj.assetsByChunkName[chunk.name] = [].concat(obj.assetsByChunkName[chunk.name]).concat([asset]); - else - obj.assetsByChunkName[chunk.name] = asset; + if (obj.assetsByChunkName[chunk.name]) + obj.assetsByChunkName[chunk.name] = [] + .concat(obj.assetsByChunkName[chunk.name]) + .concat([asset]); + else obj.assetsByChunkName[chunk.name] = asset; } } } @@ -316,16 +380,19 @@ class Stats { obj.assets.sort(sortByField(sortAssets)); } - if(showEntrypoints) { + if (showEntrypoints) { obj.entrypoints = {}; - for(const keyValuePair of compilation.entrypoints) { + for (const keyValuePair of compilation.entrypoints) { const name = keyValuePair[0]; const ep = keyValuePair[1]; obj.entrypoints[name] = { chunks: ep.chunks.map(c => c.id), - assets: ep.chunks.reduce((array, c) => array.concat(c.files || []), []) + assets: ep.chunks.reduce( + (array, c) => array.concat(c.files || []), + [] + ) }; - if(showPerformance) { + if (showPerformance) { obj.entrypoints[name].isOverSizeLimit = ep.isOverSizeLimit; } } @@ -334,8 +401,8 @@ class Stats { const fnModule = module => { const path = []; let current = module; - while(current.issuer) { - path.push(current = current.issuer); + while (current.issuer) { + path.push((current = current.issuer)); } path.reverse(); const obj = { @@ -353,55 +420,68 @@ class Stats { assets: Object.keys(module.assets || {}), issuer: module.issuer && module.issuer.identifier(), issuerId: module.issuer && module.issuer.id, - issuerName: module.issuer && module.issuer.readableIdentifier(requestShortener), - issuerPath: module.issuer && path.map(module => ({ - id: module.id, - identifier: module.identifier(), - name: module.readableIdentifier(requestShortener), - profile: module.profile - })), + issuerName: + module.issuer && module.issuer.readableIdentifier(requestShortener), + issuerPath: + module.issuer && + path.map(module => ({ + id: module.id, + identifier: module.identifier(), + name: module.readableIdentifier(requestShortener), + profile: module.profile + })), profile: module.profile, failed: !!module.error, errors: module.errors ? module.errors.length : 0, warnings: module.warnings ? module.warnings.length : 0 }; - if(showReasons) { - obj.reasons = module.reasons.map(reason => { - const obj = { - moduleId: reason.module ? reason.module.id : null, - moduleIdentifier: reason.module ? reason.module.identifier() : null, - module: reason.module ? reason.module.readableIdentifier(requestShortener) : null, - moduleName: reason.module ? reason.module.readableIdentifier(requestShortener) : null, - type: reason.dependency ? reason.dependency.type : null, - userRequest: reason.dependency ? reason.dependency.userRequest : null - }; - if(reason.dependency) { - const locInfo = formatLocation(reason.dependency.loc); - if(locInfo) obj.loc = locInfo; - } - return obj; - }).sort((a, b) => a.moduleId - b.moduleId); + if (showReasons) { + obj.reasons = module.reasons + .map(reason => { + const obj = { + moduleId: reason.module ? reason.module.id : null, + moduleIdentifier: reason.module + ? reason.module.identifier() + : null, + module: reason.module + ? reason.module.readableIdentifier(requestShortener) + : null, + moduleName: reason.module + ? reason.module.readableIdentifier(requestShortener) + : null, + type: reason.dependency ? reason.dependency.type : null, + userRequest: reason.dependency + ? reason.dependency.userRequest + : null + }; + if (reason.dependency) { + const locInfo = formatLocation(reason.dependency.loc); + if (locInfo) obj.loc = locInfo; + } + return obj; + }) + .sort((a, b) => a.moduleId - b.moduleId); } - if(showUsedExports) { - if(module.used === true) - obj.usedExports = module.usedExports; - else if(module.used === false) - obj.usedExports = false; + if (showUsedExports) { + if (module.used === true) obj.usedExports = module.usedExports; + else if (module.used === false) obj.usedExports = false; } - if(showProvidedExports) { - obj.providedExports = Array.isArray(module.buildMeta.providedExports) ? module.buildMeta.providedExports : null; + if (showProvidedExports) { + obj.providedExports = Array.isArray(module.buildMeta.providedExports) + ? module.buildMeta.providedExports + : null; } - if(showOptimizationBailout) { + if (showOptimizationBailout) { obj.optimizationBailout = module.optimizationBailout.map(item => { - if(typeof item === "function") return item(requestShortener); + if (typeof item === "function") return item(requestShortener); return item; }); } - if(showDepth) { + if (showDepth) { obj.depth = module.depth; } - if(showNestedModules) { - if(module.modules) { + if (showNestedModules) { + if (module.modules) { const modules = module.modules; obj.modules = modules .sort(sortByField("depth")) @@ -411,30 +491,29 @@ class Stats { obj.modules.sort(sortByField(sortModules)); } } - if(showSource && module._source) { + if (showSource && module._source) { obj.source = module._source.source(); } return obj; }; - if(showChunks) { + if (showChunks) { obj.chunks = compilation.chunks.map(chunk => { const parents = new Set(); const children = new Set(); const siblings = new Set(); - for(const chunkGroup of chunk.groupsIterable) { - for(const parentGroup of chunkGroup.parentsIterable) { - for(const chunk of parentGroup.chunks) { + for (const chunkGroup of chunk.groupsIterable) { + for (const parentGroup of chunkGroup.parentsIterable) { + for (const chunk of parentGroup.chunks) { parents.add(chunk.id); } } - for(const childGroup of chunkGroup.childrenIterable) { - for(const chunk of childGroup.chunks) { + for (const childGroup of chunkGroup.childrenIterable) { + for (const chunk of childGroup.chunks) { children.add(chunk.id); } } - for(const sibling of chunkGroup.chunks) { - if(sibling !== chunk) - siblings.add(sibling.id); + for (const sibling of chunkGroup.chunks) { + if (sibling !== chunk) siblings.add(sibling.id); } } const obj = { @@ -452,7 +531,7 @@ class Stats { parents: Array.from(parents).sort(), children: Array.from(children).sort() }; - if(showChunkModules) { + if (showChunkModules) { obj.modules = chunk .getModules() .sort(sortByField("depth")) @@ -461,26 +540,40 @@ class Stats { obj.filteredModules = chunk.getNumberOfModules() - obj.modules.length; obj.modules.sort(sortByField(sortModules)); } - if(showChunkOrigins) { + if (showChunkOrigins) { obj.origins = Array.from(chunk.groupsIterable, g => g.origins) .reduce((a, b) => a.concat(b), []) .map(origin => ({ moduleId: origin.module ? origin.module.id : undefined, module: origin.module ? origin.module.identifier() : "", moduleIdentifier: origin.module ? origin.module.identifier() : "", - moduleName: origin.module ? origin.module.readableIdentifier(requestShortener) : "", + moduleName: origin.module + ? origin.module.readableIdentifier(requestShortener) + : "", loc: formatLocation(origin.loc), request: origin.request, reasons: origin.reasons || [] - })).sort((a, b) => { - if(typeof a.moduleId === "number" && typeof b.moduleId !== "number") return 1; - if(typeof a.moduleId !== "number" && typeof b.moduleId === "number") return -1; - if(typeof a.moduleId === "number" && typeof b.moduleId === "number") { + })) + .sort((a, b) => { + if ( + typeof a.moduleId === "number" && + typeof b.moduleId !== "number" + ) + return 1; + if ( + typeof a.moduleId !== "number" && + typeof b.moduleId === "number" + ) + return -1; + if ( + typeof a.moduleId === "number" && + typeof b.moduleId === "number" + ) { const diffId = a.moduleId - b.moduleId; - if(diffId !== 0) return diffId; + if (diffId !== 0) return diffId; } - if(a.loc < b.loc) return -1; - if(a.loc > b.loc) return 1; + if (a.loc < b.loc) return -1; + if (a.loc > b.loc) return 1; return 0; }); } @@ -488,7 +581,7 @@ class Stats { }); obj.chunks.sort(sortByField(sortChunks)); } - if(showModules) { + if (showModules) { obj.modules = compilation.modules .slice() .sort(sortByField("depth")) @@ -497,14 +590,18 @@ class Stats { obj.filteredModules = compilation.modules.length - obj.modules.length; obj.modules.sort(sortByField(sortModules)); } - if(showChildren) { + if (showChildren) { obj.children = compilation.children.map((child, idx) => { const childOptions = Stats.getChildOptions(options, idx); const obj = new Stats(child).toJson(childOptions, forToString); delete obj.hash; delete obj.version; - if(child.name) - obj.name = identifierUtils.makePathsRelative(context, child.name, compilation.cache); + if (child.name) + obj.name = identifierUtils.makePathsRelative( + context, + child.name, + compilation.cache + ); return obj; }); } @@ -513,9 +610,9 @@ class Stats { } toString(options) { - if(typeof options === "boolean" || typeof options === "string") { + if (typeof options === "boolean" || typeof options === "string") { options = Stats.presetToOptions(options); - } else if(!options) { + } else if (!options) { options = {}; } @@ -538,39 +635,38 @@ class Stats { magenta: "\u001b[1m\u001b[35m" }; - const colors = Object.keys(defaultColors).reduce((obj, color) => { - obj[color] = str => { - if(useColors) { - buf.push( - (useColors === true || useColors[color] === undefined) ? - defaultColors[color] : useColors[color] - ); - } - buf.push(str); - if(useColors) { - buf.push("\u001b[39m\u001b[22m"); - } - }; - return obj; - }, { - normal: (str) => buf.push(str) - }); + const colors = Object.keys(defaultColors).reduce( + (obj, color) => { + obj[color] = str => { + if (useColors) { + buf.push( + useColors === true || useColors[color] === undefined + ? defaultColors[color] + : useColors[color] + ); + } + buf.push(str); + if (useColors) { + buf.push("\u001b[39m\u001b[22m"); + } + }; + return obj; + }, + { + normal: str => buf.push(str) + } + ); - const coloredTime = (time) => { + const coloredTime = time => { let times = [800, 400, 200, 100]; - if(obj.time) { + if (obj.time) { times = [obj.time / 2, obj.time / 4, obj.time / 8, obj.time / 16]; } - if(time < times[3]) - colors.normal(`${time}ms`); - else if(time < times[2]) - colors.bold(`${time}ms`); - else if(time < times[1]) - colors.green(`${time}ms`); - else if(time < times[0]) - colors.yellow(`${time}ms`); - else - colors.red(`${time}ms`); + if (time < times[3]) colors.normal(`${time}ms`); + else if (time < times[2]) colors.bold(`${time}ms`); + else if (time < times[1]) colors.green(`${time}ms`); + else if (time < times[0]) colors.yellow(`${time}ms`); + else colors.red(`${time}ms`); }; const newline = () => buf.push("\n"); @@ -583,28 +679,24 @@ class Stats { const rows = array.length; const cols = array[0].length; const colSizes = new Array(cols); - for(let col = 0; col < cols; col++) - colSizes[col] = 0; - for(let row = 0; row < rows; row++) { - for(let col = 0; col < cols; col++) { + for (let col = 0; col < cols; col++) colSizes[col] = 0; + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { const value = `${getText(array, row, col)}`; - if(value.length > colSizes[col]) { + if (value.length > colSizes[col]) { colSizes[col] = value.length; } } } - for(let row = 0; row < rows; row++) { - for(let col = 0; col < cols; col++) { + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { const format = array[row][col].color; const value = `${getText(array, row, col)}`; let l = value.length; - if(align[col] === "l") - format(value); - for(; l < colSizes[col] && col !== cols - 1; l++) - colors.normal(" "); - if(align[col] === "r") - format(value); - if(col + 1 < cols && colSizes[col] !== 0) + if (align[col] === "l") format(value); + for (; l < colSizes[col] && col !== cols - 1; l++) colors.normal(" "); + if (align[col] === "r") format(value); + if (col + 1 < cols && colSizes[col] !== 0) colors.normal(splitter || " "); } newline(); @@ -612,30 +704,30 @@ class Stats { }; const getAssetColor = (asset, defaultColor) => { - if(asset.isOverSizeLimit) { + if (asset.isOverSizeLimit) { return colors.yellow; } return defaultColor; }; - if(obj.hash) { + if (obj.hash) { colors.normal("Hash: "); colors.bold(obj.hash); newline(); } - if(obj.version) { + if (obj.version) { colors.normal("Version: webpack "); colors.bold(obj.version); newline(); } - if(typeof obj.time === "number") { + if (typeof obj.time === "number") { colors.normal("Time: "); colors.bold(obj.time); colors.normal("ms"); newline(); } - if(typeof obj.builtAt === "number") { + if (typeof obj.builtAt === "number") { const builtAtDate = new Date(obj.builtAt); colors.normal("Built at: "); colors.normal(builtAtDate.toLocaleDateString()); @@ -643,83 +735,95 @@ class Stats { colors.bold(builtAtDate.toLocaleTimeString()); newline(); } - if(obj.env) { + if (obj.env) { colors.normal("Environment (--env): "); colors.bold(JSON.stringify(obj.env, null, 2)); newline(); } - if(obj.publicPath) { + if (obj.publicPath) { colors.normal("PublicPath: "); colors.bold(obj.publicPath); newline(); } - if(obj.assets && obj.assets.length > 0) { + if (obj.assets && obj.assets.length > 0) { const t = [ - [{ - value: "Asset", - color: colors.bold - }, { - value: "Size", - color: colors.bold - }, { - value: "Chunks", - color: colors.bold - }, { - value: "", - color: colors.bold - }, { - value: "", - color: colors.bold - }, { - value: "Chunk Names", - color: colors.bold - }] + [ + { + value: "Asset", + color: colors.bold + }, + { + value: "Size", + color: colors.bold + }, + { + value: "Chunks", + color: colors.bold + }, + { + value: "", + color: colors.bold + }, + { + value: "", + color: colors.bold + }, + { + value: "Chunk Names", + color: colors.bold + } + ] ]; - for(const asset of obj.assets) { - t.push([{ - value: asset.name, - color: getAssetColor(asset, colors.green) - }, { - value: SizeFormatHelpers.formatSize(asset.size), - color: getAssetColor(asset, colors.normal) - }, { - value: asset.chunks.join(", "), - color: colors.bold - }, { - value: asset.emitted ? "[emitted]" : "", - color: colors.green - }, { - value: asset.isOverSizeLimit ? "[big]" : "", - color: getAssetColor(asset, colors.normal) - }, { - value: asset.chunkNames.join(", "), - color: colors.normal - }]); + for (const asset of obj.assets) { + t.push([ + { + value: asset.name, + color: getAssetColor(asset, colors.green) + }, + { + value: SizeFormatHelpers.formatSize(asset.size), + color: getAssetColor(asset, colors.normal) + }, + { + value: asset.chunks.join(", "), + color: colors.bold + }, + { + value: asset.emitted ? "[emitted]" : "", + color: colors.green + }, + { + value: asset.isOverSizeLimit ? "[big]" : "", + color: getAssetColor(asset, colors.normal) + }, + { + value: asset.chunkNames.join(", "), + color: colors.normal + } + ]); } table(t, "rrrlll"); } - if(obj.filteredAssets > 0) { + if (obj.filteredAssets > 0) { colors.normal(" "); - if(obj.assets.length > 0) - colors.normal("+ "); + if (obj.assets.length > 0) colors.normal("+ "); colors.normal(obj.filteredAssets); - if(obj.assets.length > 0) - colors.normal(" hidden"); + if (obj.assets.length > 0) colors.normal(" hidden"); colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset"); newline(); } - if(obj.entrypoints) { - for(const name of Object.keys(obj.entrypoints)) { + if (obj.entrypoints) { + for (const name of Object.keys(obj.entrypoints)) { const ep = obj.entrypoints[name]; colors.normal("Entrypoint "); colors.bold(name); - if(ep.isOverSizeLimit) { + if (ep.isOverSizeLimit) { colors.normal(" "); colors.yellow("[big]"); } colors.normal(" ="); - for(const asset of ep.assets) { + for (const asset of ep.assets) { colors.normal(" "); colors.green(asset); } @@ -727,119 +831,125 @@ class Stats { } } const modulesByIdentifier = {}; - if(obj.modules) { - for(const module of obj.modules) { + if (obj.modules) { + for (const module of obj.modules) { modulesByIdentifier[`$${module.identifier}`] = module; } - } else if(obj.chunks) { - for(const chunk of obj.chunks) { - if(chunk.modules) { - for(const module of chunk.modules) { + } else if (obj.chunks) { + for (const chunk of obj.chunks) { + if (chunk.modules) { + for (const module of chunk.modules) { modulesByIdentifier[`$${module.identifier}`] = module; } } } } - const processModuleAttributes = (module) => { + const processModuleAttributes = module => { colors.normal(" "); colors.normal(SizeFormatHelpers.formatSize(module.size)); - if(module.chunks) { - for(const chunk of module.chunks) { + if (module.chunks) { + for (const chunk of module.chunks) { colors.normal(" {"); colors.yellow(chunk); colors.normal("}"); } } - if(typeof module.depth === "number") { + if (typeof module.depth === "number") { colors.normal(` [depth ${module.depth}]`); } - if(module.cacheable === false) { + if (module.cacheable === false) { colors.red(" [not cacheable]"); } - if(module.optional) { + if (module.optional) { colors.yellow(" [optional]"); } - if(module.built) { + if (module.built) { colors.green(" [built]"); } - if(module.prefetched) { + if (module.prefetched) { colors.magenta(" [prefetched]"); } - if(module.failed) - colors.red(" [failed]"); - if(module.warnings) - colors.yellow(` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]`); - if(module.errors) - colors.red(` [${module.errors} error${module.errors === 1 ? "" : "s"}]`); + if (module.failed) colors.red(" [failed]"); + if (module.warnings) + colors.yellow( + ` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]` + ); + if (module.errors) + colors.red( + ` [${module.errors} error${module.errors === 1 ? "" : "s"}]` + ); }; const processModuleContent = (module, prefix) => { - if(Array.isArray(module.providedExports)) { + if (Array.isArray(module.providedExports)) { colors.normal(prefix); - if(module.providedExports.length === 0) - colors.cyan("[no exports]"); - else - colors.cyan(`[exports: ${module.providedExports.join(", ")}]`); + if (module.providedExports.length === 0) colors.cyan("[no exports]"); + else colors.cyan(`[exports: ${module.providedExports.join(", ")}]`); newline(); } - if(module.usedExports !== undefined) { - if(module.usedExports !== true) { + if (module.usedExports !== undefined) { + if (module.usedExports !== true) { colors.normal(prefix); - if(module.usedExports === null) + if (module.usedExports === null) colors.cyan("[used exports unknown]"); - else if(module.usedExports === false) + else if (module.usedExports === false) colors.cyan("[no exports used]"); - else if(Array.isArray(module.usedExports) && module.usedExports.length === 0) + else if ( + Array.isArray(module.usedExports) && + module.usedExports.length === 0 + ) colors.cyan("[no exports used]"); - else if(Array.isArray(module.usedExports)) - colors.cyan(`[only some exports used: ${module.usedExports.join(", ")}]`); + else if (Array.isArray(module.usedExports)) + colors.cyan( + `[only some exports used: ${module.usedExports.join(", ")}]` + ); newline(); } } - if(Array.isArray(module.optimizationBailout)) { - for(const item of module.optimizationBailout) { + if (Array.isArray(module.optimizationBailout)) { + for (const item of module.optimizationBailout) { colors.normal(prefix); colors.yellow(item); newline(); } } - if(module.reasons) { - for(const reason of module.reasons) { + if (module.reasons) { + for (const reason of module.reasons) { colors.normal(prefix); - if(reason.type) { + if (reason.type) { colors.normal(reason.type); colors.normal(" "); } - if(reason.userRequest) { + if (reason.userRequest) { colors.cyan(reason.userRequest); colors.normal(" "); } - if(reason.moduleId !== null) { + if (reason.moduleId !== null) { colors.normal("["); colors.normal(reason.moduleId); colors.normal("]"); } - if(reason.module && reason.module !== reason.moduleId) { + if (reason.module && reason.module !== reason.moduleId) { colors.normal(" "); colors.magenta(reason.module); } - if(reason.loc) { + if (reason.loc) { colors.normal(" "); colors.normal(reason.loc); } newline(); } } - if(module.profile) { + if (module.profile) { colors.normal(prefix); let sum = 0; - if(module.issuerPath) { - for(const m of module.issuerPath) { + if (module.issuerPath) { + for (const m of module.issuerPath) { colors.normal("["); colors.normal(m.id); colors.normal("] "); - if(m.profile) { + if (m.profile) { const time = (m.profile.factory || 0) + (m.profile.building || 0); coloredTime(time); sum += time; @@ -848,7 +958,7 @@ class Stats { colors.normal("-> "); } } - for(const key of Object.keys(module.profile)) { + for (const key of Object.keys(module.profile)) { colors.normal(`${key}:`); const time = module.profile[key]; coloredTime(time); @@ -859,118 +969,115 @@ class Stats { coloredTime(sum); newline(); } - if(module.modules) { + if (module.modules) { processModulesList(module, prefix + "| "); } }; const processModulesList = (obj, prefix) => { - if(obj.modules) { - for(const module of obj.modules) { + if (obj.modules) { + for (const module of obj.modules) { colors.normal(prefix); const name = module.name || module.identifier; let contentPrefix = prefix + " "; - if(typeof module.id === "string" || typeof module.id === "number") { + if (typeof module.id === "string" || typeof module.id === "number") { contentPrefix += " "; - if(module.id < 1000) colors.normal(" "); - if(module.id < 100) colors.normal(" "); - if(module.id < 10) colors.normal(" "); + if (module.id < 1000) colors.normal(" "); + if (module.id < 100) colors.normal(" "); + if (module.id < 10) colors.normal(" "); colors.normal("["); colors.normal(module.id); colors.normal("]"); - if(name !== module.id) - colors.normal(" "); + if (name !== module.id) colors.normal(" "); } - if(name !== module.id) { + if (name !== module.id) { colors.bold(name); } processModuleAttributes(module); newline(); processModuleContent(module, contentPrefix); } - if(obj.filteredModules > 0) { + if (obj.filteredModules > 0) { colors.normal(prefix); colors.normal(" "); - if(obj.modules.length > 0) - colors.normal(" + "); + if (obj.modules.length > 0) colors.normal(" + "); colors.normal(obj.filteredModules); - if(obj.modules.length > 0) - colors.normal(" hidden"); + if (obj.modules.length > 0) colors.normal(" hidden"); colors.normal(obj.filteredModules !== 1 ? " modules" : " module"); newline(); } } }; - if(obj.chunks) { - for(const chunk of obj.chunks) { + if (obj.chunks) { + for (const chunk of obj.chunks) { colors.normal("chunk "); - if(chunk.id < 1000) colors.normal(" "); - if(chunk.id < 100) colors.normal(" "); - if(chunk.id < 10) colors.normal(" "); + if (chunk.id < 1000) colors.normal(" "); + if (chunk.id < 100) colors.normal(" "); + if (chunk.id < 10) colors.normal(" "); colors.normal("{"); colors.yellow(chunk.id); colors.normal("} "); colors.green(chunk.files.join(", ")); - if(chunk.names && chunk.names.length > 0) { + if (chunk.names && chunk.names.length > 0) { colors.normal(" ("); colors.normal(chunk.names.join(", ")); colors.normal(")"); } colors.normal(" "); colors.normal(SizeFormatHelpers.formatSize(chunk.size)); - for(const id of chunk.parents) { + for (const id of chunk.parents) { colors.normal(" <{"); colors.yellow(id); colors.normal("}>"); } - for(const id of chunk.siblings) { + for (const id of chunk.siblings) { colors.normal(" ={"); colors.yellow(id); colors.normal("}="); } - for(const id of chunk.children) { + for (const id of chunk.children) { colors.normal(" >{"); colors.yellow(id); colors.normal("}<"); } - if(chunk.entry) { + if (chunk.entry) { colors.yellow(" [entry]"); - } else if(chunk.initial) { + } else if (chunk.initial) { colors.yellow(" [initial]"); } - if(chunk.rendered) { + if (chunk.rendered) { colors.green(" [rendered]"); } - if(chunk.recorded) { + if (chunk.recorded) { colors.green(" [recorded]"); } - if(chunk.reason) { + if (chunk.reason) { colors.yellow(` ${chunk.reason}`); } newline(); - if(chunk.origins) { - for(const origin of chunk.origins) { + if (chunk.origins) { + for (const origin of chunk.origins) { colors.normal(" > "); - if(origin.reasons && origin.reasons.length) { + if (origin.reasons && origin.reasons.length) { colors.yellow(origin.reasons.join(" ")); colors.normal(" "); } - if(origin.request) { + if (origin.request) { colors.normal(origin.request); colors.normal(" "); } - if(origin.module) { + if (origin.module) { colors.normal("["); colors.normal(origin.moduleId); colors.normal("] "); const module = modulesByIdentifier[`$${origin.module}`]; - if(module) { + if (module) { colors.bold(module.name); colors.normal(" "); } } - if(origin.loc) { + if (origin.loc) { colors.normal(origin.loc); } newline(); @@ -982,25 +1089,25 @@ class Stats { processModulesList(obj, ""); - if(obj._showWarnings && obj.warnings) { - for(const warning of obj.warnings) { + if (obj._showWarnings && obj.warnings) { + for (const warning of obj.warnings) { newline(); colors.yellow(`WARNING in ${warning}`); newline(); } } - if(obj._showErrors && obj.errors) { - for(const error of obj.errors) { + if (obj._showErrors && obj.errors) { + for (const error of obj.errors) { newline(); colors.red(`ERROR in ${error}`); newline(); } } - if(obj.children) { - for(const child of obj.children) { + if (obj.children) { + for (const child of obj.children) { const childString = Stats.jsonToString(child, useColors); - if(childString) { - if(child.name) { + if (childString) { + if (child.name) { colors.normal("Child "); colors.bold(child.name); colors.normal(":"); @@ -1014,19 +1121,22 @@ class Stats { } } } - if(obj.needAdditionalPass) { - colors.yellow("Compilation needs an additional pass and will compile again."); + if (obj.needAdditionalPass) { + colors.yellow( + "Compilation needs an additional pass and will compile again." + ); } - while(buf[buf.length - 1] === "\n") buf.pop(); + while (buf[buf.length - 1] === "\n") buf.pop(); return buf.join(""); } static presetToOptions(name) { // Accepted values: none, errors-only, minimal, normal, detailed, verbose // Any other falsy value will behave as 'none', truthy values as 'normal' - const pn = (typeof name === "string") && name.toLowerCase() || name || "none"; - switch(pn) { + const pn = + (typeof name === "string" && name.toLowerCase()) || name || "none"; + switch (pn) { case "none": return { all: false @@ -1047,7 +1157,7 @@ class Stats { errorDetails: true, publicPath: true, exclude: () => false, - maxModules: Infinity, + maxModules: Infinity }; case "detailed": return { @@ -1062,7 +1172,7 @@ class Stats { errorDetails: true, publicPath: true, exclude: () => false, - maxModules: Infinity, + maxModules: Infinity }; case "minimal": return { @@ -1070,13 +1180,13 @@ class Stats { modules: true, maxModules: 0, errors: true, - warnings: true, + warnings: true }; case "errors-only": return { all: false, errors: true, - moduleTrace: true, + moduleTrace: true }; default: return {}; @@ -1085,16 +1195,14 @@ class Stats { static getChildOptions(options, idx) { let innerOptions; - if(Array.isArray(options.children)) { - if(idx < options.children.length) - innerOptions = options.children[idx]; - } else if(typeof options.children === "object" && options.children) { + if (Array.isArray(options.children)) { + if (idx < options.children.length) innerOptions = options.children[idx]; + } else if (typeof options.children === "object" && options.children) { innerOptions = options.children; } - if(typeof innerOptions === "boolean" || typeof innerOptions === "string") + if (typeof innerOptions === "boolean" || typeof innerOptions === "string") innerOptions = Stats.presetToOptions(innerOptions); - if(!innerOptions) - return options; + if (!innerOptions) return options; const childOptions = Object.assign({}, options); delete childOptions.children; // do not inherit children return Object.assign(childOptions, innerOptions); diff --git a/lib/Template.js b/lib/Template.js index 55c3162c8..d045e3241 100644 --- a/lib/Template.js +++ b/lib/Template.js @@ -10,7 +10,7 @@ const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0); const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0); const DELTA_A_TO_Z = "z".charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1; const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g; -const INDENT_MULTILINE_REGEX = /^\t/mg; +const INDENT_MULTILINE_REGEX = /^\t/gm; const LINE_SEPARATOR_REGEX = /\r?\n/g; const IDENTIFIER_NAME_REPLACE_REGEX = /^([^a-zA-Z$_])/; const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-zA-Z0-9$]+/g; @@ -21,8 +21,8 @@ const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g; const stringifyIdSortPredicate = (a, b) => { var aId = a.id + ""; var bId = b.id + ""; - if(aId < bId) return -1; - if(aId > bId) return 1; + if (aId < bId) return -1; + if (aId > bId) return 1; return 0; }; @@ -32,99 +32,122 @@ const moduleIdIsNumber = module => { module.exports = class Template { static getFunctionContent(fn) { - return fn.toString().replace(FUNCTION_CONTENT_REGEX, "").replace(INDENT_MULTILINE_REGEX, "").replace(LINE_SEPARATOR_REGEX, "\n"); + return fn + .toString() + .replace(FUNCTION_CONTENT_REGEX, "") + .replace(INDENT_MULTILINE_REGEX, "") + .replace(LINE_SEPARATOR_REGEX, "\n"); } static toIdentifier(str) { - if(typeof str !== "string") return ""; - return str.replace(IDENTIFIER_NAME_REPLACE_REGEX, "_$1").replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_"); + if (typeof str !== "string") return ""; + return str + .replace(IDENTIFIER_NAME_REPLACE_REGEX, "_$1") + .replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_"); } static toComment(str) { - if(!str) return ""; + if (!str) return ""; return `/*! ${str.replace(COMMENT_END_REGEX, "* /")} */`; } static toNormalComment(str) { - if(!str) return ""; + if (!str) return ""; return `/* ${str.replace(COMMENT_END_REGEX, "* /")} */`; } static toPath(str) { - if(typeof str !== "string") return ""; - return str.replace(PATH_NAME_NORMALIZE_REPLACE_REGEX, "-").replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, ""); + if (typeof str !== "string") return ""; + return str + .replace(PATH_NAME_NORMALIZE_REPLACE_REGEX, "-") + .replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, ""); } // map number to a single character a-z, A-Z or <_ + number> if number is too big static numberToIdentifer(n) { // lower case - if(n < DELTA_A_TO_Z) return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n); + if (n < DELTA_A_TO_Z) + return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n); // upper case n -= DELTA_A_TO_Z; - if(n < DELTA_A_TO_Z) return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n); + if (n < DELTA_A_TO_Z) + return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n); // use multiple letters - return Template.numberToIdentifer(n % (2 * DELTA_A_TO_Z)) + Template.numberToIdentifer(Math.floor(n / (2 * DELTA_A_TO_Z))); + return ( + Template.numberToIdentifer(n % (2 * DELTA_A_TO_Z)) + + Template.numberToIdentifer(Math.floor(n / (2 * DELTA_A_TO_Z))) + ); } static indent(str) { - if(Array.isArray(str)) { + if (Array.isArray(str)) { return str.map(Template.indent).join("\n"); } else { str = str.trimRight(); - if(!str) return ""; - var ind = (str[0] === "\n" ? "" : "\t"); + if (!str) return ""; + var ind = str[0] === "\n" ? "" : "\t"; return ind + str.replace(/\n([^\n])/g, "\n\t$1"); } } static prefix(str, prefix) { - if(Array.isArray(str)) { + if (Array.isArray(str)) { str = str.join("\n"); } str = str.trim(); - if(!str) return ""; - const ind = (str[0] === "\n" ? "" : prefix); + if (!str) return ""; + const ind = str[0] === "\n" ? "" : prefix; return ind + str.replace(/\n([^\n])/g, "\n" + prefix + "$1"); } static asString(str) { - if(Array.isArray(str)) { + if (Array.isArray(str)) { return str.join("\n"); } return str; } static getModulesArrayBounds(modules) { - if(!modules.every(moduleIdIsNumber)) - return false; + if (!modules.every(moduleIdIsNumber)) return false; var maxId = -Infinity; var minId = Infinity; - for(const module of modules) { - if(maxId < module.id) maxId = module.id; - if(minId > module.id) minId = module.id; + for (const module of modules) { + if (maxId < module.id) maxId = module.id; + if (minId > module.id) minId = module.id; } - if(minId < 16 + ("" + minId).length) { + if (minId < 16 + ("" + minId).length) { // add minId x ',' instead of 'Array(minId).concat(...)' minId = 0; } - var objectOverhead = modules.map(module => { - var idLength = (module.id + "").length; - return idLength + 2; - }).reduce((a, b) => { - return a + b; - }, -1); + var objectOverhead = modules + .map(module => { + var idLength = (module.id + "").length; + return idLength + 2; + }) + .reduce((a, b) => { + return a + b; + }, -1); var arrayOverhead = minId === 0 ? maxId : 16 + ("" + minId).length + maxId; return arrayOverhead < objectOverhead ? [minId, maxId] : false; } - static renderChunkModules(chunk, filterFn, moduleTemplate, dependencyTemplates, prefix) { - if(!prefix) prefix = ""; + static renderChunkModules( + chunk, + filterFn, + moduleTemplate, + dependencyTemplates, + prefix + ) { + if (!prefix) prefix = ""; var source = new ConcatSource(); const modules = chunk.getModules().filter(filterFn); var removedModules = chunk.removedModules; - if(modules.length === 0 && (!removedModules || removedModules.length === 0)) { + if ( + modules.length === 0 && + (!removedModules || removedModules.length === 0) + ) { source.add("[]"); return source; } @@ -136,8 +159,8 @@ module.exports = class Template { }) }; }); - if(removedModules && removedModules.length > 0) { - for(const id of removedModules) { + if (removedModules && removedModules.length > 0) { + for (const id of removedModules) { allModules.push({ id: id, source: "false" @@ -146,37 +169,35 @@ module.exports = class Template { } var bounds = Template.getModulesArrayBounds(allModules); - if(bounds) { + if (bounds) { // Render a spare array var minId = bounds[0]; var maxId = bounds[1]; - if(minId !== 0) source.add("Array(" + minId + ").concat("); + if (minId !== 0) source.add("Array(" + minId + ").concat("); source.add("[\n"); const modules = new Map(); - for(const module of allModules) { + for (const module of allModules) { modules.set(module.id, module); } - for(var idx = minId; idx <= maxId; idx++) { + for (var idx = minId; idx <= maxId; idx++) { var module = modules.get(idx); - if(idx !== minId) source.add(",\n"); + if (idx !== minId) source.add(",\n"); source.add("/* " + idx + " */"); - if(module) { + if (module) { source.add("\n"); source.add(module.source); } } source.add("\n" + prefix + "]"); - if(minId !== 0) source.add(")"); + if (minId !== 0) source.add(")"); } else { // Render an object source.add("{\n"); - allModules - .sort(stringifyIdSortPredicate) - .forEach((module, idx) => { - if(idx !== 0) source.add(",\n"); - source.add(`\n/***/ ${JSON.stringify(module.id)}:\n`); - source.add(module.source); - }); + allModules.sort(stringifyIdSortPredicate).forEach((module, idx) => { + if (idx !== 0) source.add(",\n"); + source.add(`\n/***/ ${JSON.stringify(module.id)}:\n`); + source.add(module.source); + }); source.add("\n\n" + prefix + "}"); } return source; diff --git a/lib/TemplatedPathPlugin.js b/lib/TemplatedPathPlugin.js index 82e0f57ba..40b8033e5 100644 --- a/lib/TemplatedPathPlugin.js +++ b/lib/TemplatedPathPlugin.js @@ -23,7 +23,7 @@ const REGEXP_HASH_FOR_TEST = new RegExp(REGEXP_HASH.source, "i"), const withHashLength = (replacer, handlerFn) => { const fn = (match, hashLength, ...args) => { const length = hashLength && parseInt(hashLength, 10); - if(length && handlerFn) { + if (length && handlerFn) { return handlerFn(length); } const hash = replacer(match, hashLength, ...args); @@ -36,8 +36,11 @@ const getReplacer = (value, allowEmpty) => { const fn = (match, ...args) => { // last argument in replacer is the entire input string const input = args[args.length - 1]; - if(value === null || value === undefined) { - if(!allowEmpty) throw new Error(`Path variable ${match} not implemented in this context: ${input}`); + if (value === null || value === undefined) { + if (!allowEmpty) + throw new Error( + `Path variable ${match} not implemented in this context: ${input}` + ); return ""; } else { return `${value}`; @@ -57,57 +60,82 @@ const replacePathVariables = (path, data) => { const moduleHash = module && (module.renderedHash || module.hash); const moduleHashWithLength = module && module.hashWithLength; - if(typeof path === "function") { + if (typeof path === "function") { path = path(data); } - if(data.noChunkHash && REGEXP_CHUNKHASH_FOR_TEST.test(path)) { - throw new Error(`Cannot use [chunkhash] for chunk in '${path}' (use [hash] instead)`); + if (data.noChunkHash && REGEXP_CHUNKHASH_FOR_TEST.test(path)) { + throw new Error( + `Cannot use [chunkhash] for chunk in '${path}' (use [hash] instead)` + ); } - return path - .replace(REGEXP_HASH, withHashLength(getReplacer(data.hash), data.hashWithLength)) - .replace(REGEXP_CHUNKHASH, withHashLength(getReplacer(chunkHash), chunkHashWithLength)) - .replace(REGEXP_MODULEHASH, withHashLength(getReplacer(moduleHash), moduleHashWithLength)) - .replace(REGEXP_ID, getReplacer(chunkId)) - .replace(REGEXP_MODULEID, getReplacer(moduleId)) - .replace(REGEXP_NAME, getReplacer(chunkName)) - .replace(REGEXP_FILE, getReplacer(data.filename)) - .replace(REGEXP_FILEBASE, getReplacer(data.basename)) - // query is optional, it's OK if it's in a path but there's nothing to replace it with - .replace(REGEXP_QUERY, getReplacer(data.query, true)); + return ( + path + .replace( + REGEXP_HASH, + withHashLength(getReplacer(data.hash), data.hashWithLength) + ) + .replace( + REGEXP_CHUNKHASH, + withHashLength(getReplacer(chunkHash), chunkHashWithLength) + ) + .replace( + REGEXP_MODULEHASH, + withHashLength(getReplacer(moduleHash), moduleHashWithLength) + ) + .replace(REGEXP_ID, getReplacer(chunkId)) + .replace(REGEXP_MODULEID, getReplacer(moduleId)) + .replace(REGEXP_NAME, getReplacer(chunkName)) + .replace(REGEXP_FILE, getReplacer(data.filename)) + .replace(REGEXP_FILEBASE, getReplacer(data.basename)) + // query is optional, it's OK if it's in a path but there's nothing to replace it with + .replace(REGEXP_QUERY, getReplacer(data.query, true)) + ); }; class TemplatedPathPlugin { apply(compiler) { - compiler.hooks.compilation.tap("TemplatedPathPlugin", (compilation) => { + compiler.hooks.compilation.tap("TemplatedPathPlugin", compilation => { const mainTemplate = compilation.mainTemplate; - mainTemplate.hooks.assetPath.tap("TemplatedPathPlugin", replacePathVariables); + mainTemplate.hooks.assetPath.tap( + "TemplatedPathPlugin", + replacePathVariables + ); - mainTemplate.hooks.globalHash.tap("TemplatedPathPlugin", (chunk, paths) => { - const outputOptions = mainTemplate.outputOptions; - const publicPath = outputOptions.publicPath || ""; - const filename = outputOptions.filename || ""; - const chunkFilename = outputOptions.chunkFilename || outputOptions.filename; - if(REGEXP_HASH_FOR_TEST.test(publicPath) || REGEXP_CHUNKHASH_FOR_TEST.test(publicPath) || REGEXP_NAME_FOR_TEST.test(publicPath)) - return true; - if(REGEXP_HASH_FOR_TEST.test(filename)) - return true; - if(REGEXP_HASH_FOR_TEST.test(chunkFilename)) - return true; - if(REGEXP_HASH_FOR_TEST.test(paths.join("|"))) - return true; - }); + mainTemplate.hooks.globalHash.tap( + "TemplatedPathPlugin", + (chunk, paths) => { + const outputOptions = mainTemplate.outputOptions; + const publicPath = outputOptions.publicPath || ""; + const filename = outputOptions.filename || ""; + const chunkFilename = + outputOptions.chunkFilename || outputOptions.filename; + if ( + REGEXP_HASH_FOR_TEST.test(publicPath) || + REGEXP_CHUNKHASH_FOR_TEST.test(publicPath) || + REGEXP_NAME_FOR_TEST.test(publicPath) + ) + return true; + if (REGEXP_HASH_FOR_TEST.test(filename)) return true; + if (REGEXP_HASH_FOR_TEST.test(chunkFilename)) return true; + if (REGEXP_HASH_FOR_TEST.test(paths.join("|"))) return true; + } + ); - mainTemplate.hooks.hashForChunk.tap("TemplatedPathPlugin", (hash, chunk) => { - const outputOptions = mainTemplate.outputOptions; - const chunkFilename = outputOptions.chunkFilename || outputOptions.filename; - if(REGEXP_CHUNKHASH_FOR_TEST.test(chunkFilename)) - hash.update(JSON.stringify(chunk.getChunkMaps(true).hash)); - if(REGEXP_NAME_FOR_TEST.test(chunkFilename)) - hash.update(JSON.stringify(chunk.getChunkMaps(true).name)); - }); + mainTemplate.hooks.hashForChunk.tap( + "TemplatedPathPlugin", + (hash, chunk) => { + const outputOptions = mainTemplate.outputOptions; + const chunkFilename = + outputOptions.chunkFilename || outputOptions.filename; + if (REGEXP_CHUNKHASH_FOR_TEST.test(chunkFilename)) + hash.update(JSON.stringify(chunk.getChunkMaps(true).hash)); + if (REGEXP_NAME_FOR_TEST.test(chunkFilename)) + hash.update(JSON.stringify(chunk.getChunkMaps(true).name)); + } + ); }); } } diff --git a/lib/UmdMainTemplatePlugin.js b/lib/UmdMainTemplatePlugin.js index 0e0f15a10..1c50288a9 100644 --- a/lib/UmdMainTemplatePlugin.js +++ b/lib/UmdMainTemplatePlugin.js @@ -14,16 +14,18 @@ function accessorToObjectAccess(accessor) { function accessorAccess(base, accessor) { accessor = [].concat(accessor); - return accessor.map((a, idx) => { - a = base + accessorToObjectAccess(accessor.slice(0, idx + 1)); - if(idx === accessor.length - 1) return a; - return `${a} = ${a} || {}`; - }).join(", "); + return accessor + .map((a, idx) => { + a = base + accessorToObjectAccess(accessor.slice(0, idx + 1)); + if (idx === accessor.length - 1) return a; + return `${a} = ${a} || {}`; + }) + .join(", "); } class UmdMainTemplatePlugin { constructor(name, options) { - if(typeof name === "object" && !Array.isArray(name)) { + if (typeof name === "object" && !Array.isArray(name)) { this.name = name.root || name.amd || name.commonjs; this.names = name; } else { @@ -40,19 +42,21 @@ class UmdMainTemplatePlugin { } apply(compilation) { - const { - mainTemplate, - chunkTemplate, - runtimeTemplate - } = compilation; + const { mainTemplate, chunkTemplate, runtimeTemplate } = compilation; const onRenderWithEntry = (source, chunk, hash) => { - let externals = chunk.getModules().filter(m => m.external && (m.externalType === "umd" || m.externalType === "umd2")); + let externals = chunk + .getModules() + .filter( + m => + m.external && + (m.externalType === "umd" || m.externalType === "umd2") + ); const optionalExternals = []; let requiredExternals = []; - if(this.optionalAmdExternalAsGlobal) { - for(const m of externals) { - if(m.optional) { + if (this.optionalAmdExternalAsGlobal) { + for (const m of externals) { + if (m.optional) { optionalExternals.push(m); } else { requiredExternals.push(m); @@ -71,36 +75,63 @@ class UmdMainTemplatePlugin { } function externalsDepsArray(modules) { - return `[${replaceKeys(modules.map(m => JSON.stringify(typeof m.request === "object" ? m.request.amd : m.request)).join(", "))}]`; + return `[${replaceKeys( + modules + .map(m => + JSON.stringify( + typeof m.request === "object" ? m.request.amd : m.request + ) + ) + .join(", ") + )}]`; } function externalsRootArray(modules) { - return replaceKeys(modules.map(m => { - let request = m.request; - if(typeof request === "object") request = request.root; - return `root${accessorToObjectAccess([].concat(request))}`; - }).join(", ")); + return replaceKeys( + modules + .map(m => { + let request = m.request; + if (typeof request === "object") request = request.root; + return `root${accessorToObjectAccess([].concat(request))}`; + }) + .join(", ") + ); } function externalsRequireArray(type) { - return replaceKeys(externals.map(m => { - let expr; - let request = m.request; - if(typeof request === "object") request = request[type]; - if(typeof request === "undefined") throw new Error("Missing external configuration for type:" + type); - if(Array.isArray(request)) { - expr = `require(${JSON.stringify(request[0])})${accessorToObjectAccess(request.slice(1))}`; - } else - expr = `require(${JSON.stringify(request)})`; - if(m.optional) { - expr = `(function webpackLoadOptionalExternalModule() { try { return ${expr}; } catch(e) {} }())`; - } - return expr; - }).join(", ")); + return replaceKeys( + externals + .map(m => { + let expr; + let request = m.request; + if (typeof request === "object") request = request[type]; + if (typeof request === "undefined") + throw new Error( + "Missing external configuration for type:" + type + ); + if (Array.isArray(request)) { + expr = `require(${JSON.stringify( + request[0] + )})${accessorToObjectAccess(request.slice(1))}`; + } else expr = `require(${JSON.stringify(request)})`; + if (m.optional) { + expr = `(function webpackLoadOptionalExternalModule() { try { return ${ + expr + }; } catch(e) {} }())`; + } + return expr; + }) + .join(", ") + ); } function externalsArguments(modules) { - return modules.map(m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`).join(", "); + return modules + .map( + m => + `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__` + ) + .join(", "); } function libraryName(library) { @@ -108,89 +139,125 @@ class UmdMainTemplatePlugin { } let amdFactory; - if(optionalExternals.length > 0) { + if (optionalExternals.length > 0) { const wrapperArguments = externalsArguments(requiredExternals); - const factoryArguments = requiredExternals.length > 0 ? - externalsArguments(requiredExternals) + ", " + externalsRootArray(optionalExternals) : - externalsRootArray(optionalExternals); - amdFactory = `function webpackLoadOptionalExternalModuleAmd(${wrapperArguments}) {\n` + + const factoryArguments = + requiredExternals.length > 0 + ? externalsArguments(requiredExternals) + + ", " + + externalsRootArray(optionalExternals) + : externalsRootArray(optionalExternals); + amdFactory = + `function webpackLoadOptionalExternalModuleAmd(${ + wrapperArguments + }) {\n` + ` return factory(${factoryArguments});\n` + " }"; } else { amdFactory = "factory"; } - return new ConcatSource(new OriginalSource( - "(function webpackUniversalModuleDefinition(root, factory) {\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.commonjs2 ? - " //" + this.auxiliaryComment.commonjs2 + "\n" : - "" - ) + - " if(typeof exports === 'object' && typeof module === 'object')\n" + - " module.exports = factory(" + externalsRequireArray("commonjs2") + ");\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.amd ? - " //" + this.auxiliaryComment.amd + "\n" : - "" - ) + - " else if(typeof define === 'function' && define.amd)\n" + - (requiredExternals.length > 0 ? - (this.names.amd && this.namedDefine === true ? - " define(" + libraryName(this.names.amd) + ", " + externalsDepsArray(requiredExternals) + ", " + amdFactory + ");\n" : - " define(" + externalsDepsArray(requiredExternals) + ", " + amdFactory + ");\n" - ) : - (this.names.amd && this.namedDefine === true ? - " define(" + libraryName(this.names.amd) + ", [], " + amdFactory + ");\n" : - " define([], " + amdFactory + ");\n" - ) - ) + - (this.names.root || this.names.commonjs ? - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.commonjs ? - " //" + this.auxiliaryComment.commonjs + "\n" : - "" - ) + - " else if(typeof exports === 'object')\n" + - " exports[" + libraryName(this.names.commonjs || this.names.root) + "] = factory(" + externalsRequireArray("commonjs") + ");\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.root ? - " //" + this.auxiliaryComment.root + "\n" : - "" - ) + - " else\n" + - " " + replaceKeys(accessorAccess("root", this.names.root || this.names.commonjs)) + " = factory(" + externalsRootArray(externals) + ");\n" : - " else {\n" + - (externals.length > 0 ? - " var a = typeof exports === 'object' ? factory(" + externalsRequireArray("commonjs") + ") : factory(" + externalsRootArray(externals) + ");\n" : - " var a = factory();\n" - ) + - " for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n" + - " }\n" - ) + - `})(${runtimeTemplate.outputOptions.globalObject}, function(${externalsArguments(externals)}) {\nreturn `, "webpack/universalModuleDefinition"), source, ";\n})"); + return new ConcatSource( + new OriginalSource( + "(function webpackUniversalModuleDefinition(root, factory) {\n" + + (this.auxiliaryComment && typeof this.auxiliaryComment === "string" + ? " //" + this.auxiliaryComment + "\n" + : this.auxiliaryComment.commonjs2 + ? " //" + this.auxiliaryComment.commonjs2 + "\n" + : "") + + " if(typeof exports === 'object' && typeof module === 'object')\n" + + " module.exports = factory(" + + externalsRequireArray("commonjs2") + + ");\n" + + (this.auxiliaryComment && typeof this.auxiliaryComment === "string" + ? " //" + this.auxiliaryComment + "\n" + : this.auxiliaryComment.amd + ? " //" + this.auxiliaryComment.amd + "\n" + : "") + + " else if(typeof define === 'function' && define.amd)\n" + + (requiredExternals.length > 0 + ? this.names.amd && this.namedDefine === true + ? " define(" + + libraryName(this.names.amd) + + ", " + + externalsDepsArray(requiredExternals) + + ", " + + amdFactory + + ");\n" + : " define(" + + externalsDepsArray(requiredExternals) + + ", " + + amdFactory + + ");\n" + : this.names.amd && this.namedDefine === true + ? " define(" + + libraryName(this.names.amd) + + ", [], " + + amdFactory + + ");\n" + : " define([], " + amdFactory + ");\n") + + (this.names.root || this.names.commonjs + ? (this.auxiliaryComment && + typeof this.auxiliaryComment === "string" + ? " //" + this.auxiliaryComment + "\n" + : this.auxiliaryComment.commonjs + ? " //" + this.auxiliaryComment.commonjs + "\n" + : "") + + " else if(typeof exports === 'object')\n" + + " exports[" + + libraryName(this.names.commonjs || this.names.root) + + "] = factory(" + + externalsRequireArray("commonjs") + + ");\n" + + (this.auxiliaryComment && + typeof this.auxiliaryComment === "string" + ? " //" + this.auxiliaryComment + "\n" + : this.auxiliaryComment.root + ? " //" + this.auxiliaryComment.root + "\n" + : "") + + " else\n" + + " " + + replaceKeys( + accessorAccess("root", this.names.root || this.names.commonjs) + ) + + " = factory(" + + externalsRootArray(externals) + + ");\n" + : " else {\n" + + (externals.length > 0 + ? " var a = typeof exports === 'object' ? factory(" + + externalsRequireArray("commonjs") + + ") : factory(" + + externalsRootArray(externals) + + ");\n" + : " var a = factory();\n") + + " for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n" + + " }\n") + + `})(${ + runtimeTemplate.outputOptions.globalObject + }, function(${externalsArguments(externals)}) {\nreturn `, + "webpack/universalModuleDefinition" + ), + source, + ";\n})" + ); }; - for(const template of [mainTemplate, chunkTemplate]) { - template.hooks.renderWithEntry.tap("UmdMainTemplatePlugin", onRenderWithEntry); + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "UmdMainTemplatePlugin", + onRenderWithEntry + ); } - mainTemplate.hooks.globalHashPaths.tap("UmdMainTemplatePlugin", (paths) => { - if(this.names.root) paths = paths.concat(this.names.root); - if(this.names.amd) paths = paths.concat(this.names.amd); - if(this.names.commonjs) paths = paths.concat(this.names.commonjs); + mainTemplate.hooks.globalHashPaths.tap("UmdMainTemplatePlugin", paths => { + if (this.names.root) paths = paths.concat(this.names.root); + if (this.names.amd) paths = paths.concat(this.names.amd); + if (this.names.commonjs) paths = paths.concat(this.names.commonjs); return paths; }); - mainTemplate.hooks.hash.tap("UmdMainTemplatePlugin", (hash) => { + mainTemplate.hooks.hash.tap("UmdMainTemplatePlugin", hash => { hash.update("umd"); hash.update(`${this.names.root}`); hash.update(`${this.names.amd}`); diff --git a/lib/UseStrictPlugin.js b/lib/UseStrictPlugin.js index 604c0481a..2e0743da8 100644 --- a/lib/UseStrictPlugin.js +++ b/lib/UseStrictPlugin.js @@ -8,31 +8,40 @@ const ConstDependency = require("./dependencies/ConstDependency"); class UseStrictPlugin { apply(compiler) { - compiler.hooks.compilation.tap("UseStrictPlugin", (compilation, { - normalModuleFactory - }) => { - const handler = (parser) => { - parser.hooks.program.tap("UseStrictPlugin", (ast) => { - const firstNode = ast.body[0]; - if(firstNode && - firstNode.type === "ExpressionStatement" && - firstNode.expression.type === "Literal" && - firstNode.expression.value === "use strict") { - // Remove "use strict" expression. It will be added later by the renderer again. - // This is necessary in order to not break the strict mode when webpack prepends code. - // @see https://github.com/webpack/webpack/issues/1970 - const dep = new ConstDependency("", firstNode.range); - dep.loc = firstNode.loc; - parser.state.current.addDependency(dep); - parser.state.module.buildInfo.strict = true; - } - }); - }; + compiler.hooks.compilation.tap( + "UseStrictPlugin", + (compilation, { normalModuleFactory }) => { + const handler = parser => { + parser.hooks.program.tap("UseStrictPlugin", ast => { + const firstNode = ast.body[0]; + if ( + firstNode && + firstNode.type === "ExpressionStatement" && + firstNode.expression.type === "Literal" && + firstNode.expression.value === "use strict" + ) { + // Remove "use strict" expression. It will be added later by the renderer again. + // This is necessary in order to not break the strict mode when webpack prepends code. + // @see https://github.com/webpack/webpack/issues/1970 + const dep = new ConstDependency("", firstNode.range); + dep.loc = firstNode.loc; + parser.state.current.addDependency(dep); + parser.state.module.buildInfo.strict = true; + } + }); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("UseStrictPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("UseStrictPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("UseStrictPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("UseStrictPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("UseStrictPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("UseStrictPlugin", handler); + } + ); } } diff --git a/lib/WarnCaseSensitiveModulesPlugin.js b/lib/WarnCaseSensitiveModulesPlugin.js index 102290691..d29da028e 100644 --- a/lib/WarnCaseSensitiveModulesPlugin.js +++ b/lib/WarnCaseSensitiveModulesPlugin.js @@ -8,25 +8,28 @@ const CaseSensitiveModulesWarning = require("./CaseSensitiveModulesWarning"); class WarnCaseSensitiveModulesPlugin { apply(compiler) { - compiler.hooks.compilation.tap("WarnCaseSensitiveModulesPlugin", (compilation) => { - compilation.hooks.seal.tap("WarnCaseSensitiveModulesPlugin", () => { - const moduleWithoutCase = new Map(); - for(const module of compilation.modules) { - const identifier = module.identifier().toLowerCase(); - const array = moduleWithoutCase.get(identifier); - if(array) { - array.push(module); - } else { - moduleWithoutCase.set(identifier, [module]); + compiler.hooks.compilation.tap( + "WarnCaseSensitiveModulesPlugin", + compilation => { + compilation.hooks.seal.tap("WarnCaseSensitiveModulesPlugin", () => { + const moduleWithoutCase = new Map(); + for (const module of compilation.modules) { + const identifier = module.identifier().toLowerCase(); + const array = moduleWithoutCase.get(identifier); + if (array) { + array.push(module); + } else { + moduleWithoutCase.set(identifier, [module]); + } } - } - for(const pair of moduleWithoutCase) { - const array = pair[1]; - if(array.length > 1) - compilation.warnings.push(new CaseSensitiveModulesWarning(array)); - } - }); - }); + for (const pair of moduleWithoutCase) { + const array = pair[1]; + if (array.length > 1) + compilation.warnings.push(new CaseSensitiveModulesWarning(array)); + } + }); + } + ); } } diff --git a/lib/WarnNoModeSetPlugin.js b/lib/WarnNoModeSetPlugin.js index 68366f7f4..4a69a8cca 100644 --- a/lib/WarnNoModeSetPlugin.js +++ b/lib/WarnNoModeSetPlugin.js @@ -8,7 +8,7 @@ const NoModeWarning = require("./NoModeWarning"); class WarnNoModeSetPlugin { apply(compiler) { - compiler.hooks.thisCompilation.tap("WarnNoModeSetPlugin", (compilation) => { + compiler.hooks.thisCompilation.tap("WarnNoModeSetPlugin", compilation => { compilation.warnings.push(new NoModeWarning()); }); } diff --git a/lib/WatchIgnorePlugin.js b/lib/WatchIgnorePlugin.js index 6c26e1d70..7a00e998f 100644 --- a/lib/WatchIgnorePlugin.js +++ b/lib/WatchIgnorePlugin.js @@ -15,7 +15,10 @@ class WatchIgnorePlugin { apply(compiler) { compiler.hooks.afterEnvironment.tap("WatchIgnorePlugin", () => { - compiler.watchFileSystem = new IgnoringWatchFileSystem(compiler.watchFileSystem, this.paths); + compiler.watchFileSystem = new IgnoringWatchFileSystem( + compiler.watchFileSystem, + this.paths + ); }); } } @@ -29,40 +32,65 @@ class IgnoringWatchFileSystem { } watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { - const ignored = path => this.paths.some(p => p instanceof RegExp ? p.test(path) : path.indexOf(p) === 0); + const ignored = path => + this.paths.some( + p => (p instanceof RegExp ? p.test(path) : path.indexOf(p) === 0) + ); const notIgnored = path => !ignored(path); const ignoredFiles = files.filter(ignored); const ignoredDirs = dirs.filter(ignored); - const watcher = this.wfs.watch(files.filter(notIgnored), dirs.filter(notIgnored), missing, startTime, options, (err, filesModified, dirsModified, missingModified, fileTimestamps, dirTimestamps) => { - if(err) return callback(err); + const watcher = this.wfs.watch( + files.filter(notIgnored), + dirs.filter(notIgnored), + missing, + startTime, + options, + ( + err, + filesModified, + dirsModified, + missingModified, + fileTimestamps, + dirTimestamps + ) => { + if (err) return callback(err); - for(const path of ignoredFiles) { - fileTimestamps.set(path, 1); - } + for (const path of ignoredFiles) { + fileTimestamps.set(path, 1); + } - for(const path of ignoredDirs) { - dirTimestamps.set(path, 1); - } + for (const path of ignoredDirs) { + dirTimestamps.set(path, 1); + } - callback(err, filesModified, dirsModified, missingModified, fileTimestamps, dirTimestamps); - }, callbackUndelayed); + callback( + err, + filesModified, + dirsModified, + missingModified, + fileTimestamps, + dirTimestamps + ); + }, + callbackUndelayed + ); return { close: () => watcher.close(), pause: () => watcher.pause(), getContextTimestamps: () => { const dirTimestamps = watcher.getContextTimestamps(); - for(const path of ignoredDirs) { + for (const path of ignoredDirs) { dirTimestamps.set(path, 1); } return dirTimestamps; }, getFileTimestamps: () => { const fileTimestamps = watcher.getFileTimestamps(); - for(const path of ignoredFiles) { + for (const path of ignoredFiles) { fileTimestamps.set(path, 1); } return fileTimestamps; diff --git a/lib/Watching.js b/lib/Watching.js index 38ca67fbf..19476af67 100644 --- a/lib/Watching.js +++ b/lib/Watching.js @@ -13,20 +13,21 @@ class Watching { this.handler = handler; this.callbacks = []; this.closed = false; - if(typeof watchOptions === "number") { + if (typeof watchOptions === "number") { this.watchOptions = { aggregateTimeout: watchOptions }; - } else if(watchOptions && typeof watchOptions === "object") { + } else if (watchOptions && typeof watchOptions === "object") { this.watchOptions = Object.assign({}, watchOptions); } else { this.watchOptions = {}; } - this.watchOptions.aggregateTimeout = this.watchOptions.aggregateTimeout || 200; + this.watchOptions.aggregateTimeout = + this.watchOptions.aggregateTimeout || 200; this.compiler = compiler; this.running = true; this.compiler.readRecords(err => { - if(err) return this._done(err); + if (err) return this._done(err); this._go(); }); @@ -37,33 +38,33 @@ class Watching { this.running = true; this.invalid = false; this.compiler.hooks.watchRun.callAsync(this.compiler, err => { - if(err) return this._done(err); + if (err) return this._done(err); const onCompiled = (err, compilation) => { - if(err) return this._done(err); - if(this.invalid) return this._done(); + if (err) return this._done(err); + if (this.invalid) return this._done(); - if(this.compiler.hooks.shouldEmit.call(compilation) === false) { + if (this.compiler.hooks.shouldEmit.call(compilation) === false) { return this._done(null, compilation); } this.compiler.emitAssets(compilation, err => { - if(err) return this._done(err); - if(this.invalid) return this._done(); + if (err) return this._done(err); + if (this.invalid) return this._done(); this.compiler.emitRecords(err => { - if(err) return this._done(err); + if (err) return this._done(err); - if(compilation.hooks.needAdditionalPass.call()) { + if (compilation.hooks.needAdditionalPass.call()) { compilation.needAdditionalPass = true; const stats = new Stats(compilation); stats.startTime = this.startTime; stats.endTime = Date.now(); this.compiler.hooks.done.callAsync(stats, err => { - if(err) return this._done(err); + if (err) return this._done(err); this.compiler.hooks.additionalPass.callAsync(err => { - if(err) return this._done(err); + if (err) return this._done(err); this.compiler.compile(onCompiled); }); }); @@ -86,10 +87,10 @@ class Watching { _done(err, compilation) { this.running = false; - if(this.invalid) return this._go(); + if (this.invalid) return this._go(); const stats = compilation ? this._getStats(compilation) : null; - if(err) { + if (err) { this.compiler.hooks.failed.call(err); this.handler(err, stats); return; @@ -97,34 +98,53 @@ class Watching { this.compiler.hooks.done.callAsync(stats, () => { this.handler(null, stats); - if(!this.closed) { - this.watch(Array.from(compilation.fileDependencies), Array.from(compilation.contextDependencies), Array.from(compilation.missingDependencies)); + if (!this.closed) { + this.watch( + Array.from(compilation.fileDependencies), + Array.from(compilation.contextDependencies), + Array.from(compilation.missingDependencies) + ); } - for(const cb of this.callbacks) cb(); + for (const cb of this.callbacks) cb(); this.callbacks.length = 0; }); } watch(files, dirs, missing) { this.pausedWatcher = null; - this.watcher = this.compiler.watchFileSystem.watch(files, dirs, missing, this.startTime, this.watchOptions, (err, filesModified, contextModified, missingModified, fileTimestamps, contextTimestamps) => { - this.pausedWatcher = this.watcher; - this.watcher = null; - if(err) return this.handler(err); + this.watcher = this.compiler.watchFileSystem.watch( + files, + dirs, + missing, + this.startTime, + this.watchOptions, + ( + err, + filesModified, + contextModified, + missingModified, + fileTimestamps, + contextTimestamps + ) => { + this.pausedWatcher = this.watcher; + this.watcher = null; + if (err) return this.handler(err); - this.compiler.fileTimestamps = fileTimestamps; - this.compiler.contextTimestamps = contextTimestamps; - this._invalidate(); - }, (fileName, changeTime) => { - this.compiler.hooks.invalid.call(fileName, changeTime); - }); + this.compiler.fileTimestamps = fileTimestamps; + this.compiler.contextTimestamps = contextTimestamps; + this._invalidate(); + }, + (fileName, changeTime) => { + this.compiler.hooks.invalid.call(fileName, changeTime); + } + ); } invalidate(callback) { - if(callback) { + if (callback) { this.callbacks.push(callback); } - if(this.watcher) { + if (this.watcher) { this.compiler.fileTimestamps = this.watcher.getFileTimestamps(); this.compiler.contextTimestamps = this.watcher.getContextTimestamps(); } @@ -132,12 +152,12 @@ class Watching { } _invalidate() { - if(this.watcher) { + if (this.watcher) { this.pausedWatcher = this.watcher; this.watcher.pause(); this.watcher = null; } - if(this.running) { + if (this.running) { this.invalid = true; return false; } else { @@ -146,18 +166,18 @@ class Watching { } close(callback) { - if(callback === undefined) callback = () => {}; + if (callback === undefined) callback = () => {}; this.closed = true; - if(this.watcher) { + if (this.watcher) { this.watcher.close(); this.watcher = null; } - if(this.pausedWatcher) { + if (this.pausedWatcher) { this.pausedWatcher.close(); this.pausedWatcher = null; } - if(this.running) { + if (this.running) { this.invalid = true; this._done = () => { this.compiler.hooks.watchClose.call(); diff --git a/lib/WebAssemblyModulesPlugin.js b/lib/WebAssemblyModulesPlugin.js index 303087b91..32ec3250b 100644 --- a/lib/WebAssemblyModulesPlugin.js +++ b/lib/WebAssemblyModulesPlugin.js @@ -10,44 +10,61 @@ const WebAssemblyImportDependency = require("./dependencies/WebAssemblyImportDep class WebAssemblyModulesPlugin { apply(compiler) { - compiler.hooks.compilation.tap("WebAssemblyModulesPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(WebAssemblyImportDependency, normalModuleFactory); + compiler.hooks.compilation.tap( + "WebAssemblyModulesPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + WebAssemblyImportDependency, + normalModuleFactory + ); - normalModuleFactory.hooks.createParser.for("webassembly/experimental").tap("WebAssemblyModulesPlugin", () => { - return new WebAssemblyParser(); - }); + normalModuleFactory.hooks.createParser + .for("webassembly/experimental") + .tap("WebAssemblyModulesPlugin", () => { + return new WebAssemblyParser(); + }); - normalModuleFactory.hooks.createGenerator.for("webassembly/experimental").tap("WebAssemblyModulesPlugin", () => { - return new WebAssemblyGenerator(); - }); + normalModuleFactory.hooks.createGenerator + .for("webassembly/experimental") + .tap("WebAssemblyModulesPlugin", () => { + return new WebAssemblyGenerator(); + }); - compilation.chunkTemplate.hooks.renderManifest.tap("WebAssemblyModulesPlugin", (result, options) => { - const chunk = options.chunk; - const outputOptions = options.outputOptions; - const moduleTemplates = options.moduleTemplates; - const dependencyTemplates = options.dependencyTemplates; + compilation.chunkTemplate.hooks.renderManifest.tap( + "WebAssemblyModulesPlugin", + (result, options) => { + const chunk = options.chunk; + const outputOptions = options.outputOptions; + const moduleTemplates = options.moduleTemplates; + const dependencyTemplates = options.dependencyTemplates; - for(const module of chunk.modulesIterable) { - if(module.type && module.type.startsWith("webassembly")) { - const filenameTemplate = outputOptions.webassemblyModuleFilename; + for (const module of chunk.modulesIterable) { + if (module.type && module.type.startsWith("webassembly")) { + const filenameTemplate = + outputOptions.webassemblyModuleFilename; - result.push({ - render: () => this.renderWebAssembly(module, moduleTemplates.webassembly, dependencyTemplates), - filenameTemplate, - pathOptions: { - module - }, - identifier: `webassemblyModule${module.id}`, - hash: module.hash - }); + result.push({ + render: () => + this.renderWebAssembly( + module, + moduleTemplates.webassembly, + dependencyTemplates + ), + filenameTemplate, + pathOptions: { + module + }, + identifier: `webassemblyModule${module.id}`, + hash: module.hash + }); + } + } + + return result; } - } - - return result; - }); - }); + ); + } + ); } renderWebAssembly(module, moduleTemplate, dependencyTemplates) { diff --git a/lib/WebAssemblyParser.js b/lib/WebAssemblyParser.js index bcc01b173..1740b70a8 100644 --- a/lib/WebAssemblyParser.js +++ b/lib/WebAssemblyParser.js @@ -27,16 +27,26 @@ class WebAssemblyParser extends Tapable { // extract exports // TODO find more efficient way doing it // TODO use Promises - if(typeof WebAssembly !== "undefined") { - WebAssembly.compile(source).then(module => { - state.module.buildMeta.providedExports = WebAssembly.Module.exports(module).map(exp => exp.name); - for(const imp of WebAssembly.Module.imports(module)) { - const dep = new WebAssemblyImportDependency(imp.module, imp.name, imp.kind); - state.module.addDependency(dep); - } - }).then(() => callback(null, state), err => callback(err)); + if (typeof WebAssembly !== "undefined") { + WebAssembly.compile(source) + .then(module => { + state.module.buildMeta.providedExports = WebAssembly.Module.exports( + module + ).map(exp => exp.name); + for (const imp of WebAssembly.Module.imports(module)) { + const dep = new WebAssemblyImportDependency( + imp.module, + imp.name, + imp.kind + ); + state.module.addDependency(dep); + } + }) + .then(() => callback(null, state), err => callback(err)); } else { - throw new Error("Can't compile WebAssembly modules without WebAssembly support in current node.js version (Update to latest node.js version)"); + throw new Error( + "Can't compile WebAssembly modules without WebAssembly support in current node.js version (Update to latest node.js version)" + ); } } } diff --git a/lib/WebpackOptionsApply.js b/lib/WebpackOptionsApply.js index 39ea640f9..4c89a071e 100644 --- a/lib/WebpackOptionsApply.js +++ b/lib/WebpackOptionsApply.js @@ -68,10 +68,11 @@ class WebpackOptionsApply extends OptionsApply { let ExternalsPlugin; compiler.outputPath = options.output.path; compiler.recordsInputPath = options.recordsInputPath || options.recordsPath; - compiler.recordsOutputPath = options.recordsOutputPath || options.recordsPath; + compiler.recordsOutputPath = + options.recordsOutputPath || options.recordsPath; compiler.name = options.name; compiler.dependencies = options.dependencies; - if(typeof options.target === "string") { + if (typeof options.target === "string") { let JsonpTemplatePlugin; let FetchCompileWasmTemplatePlugin; let ReadFileCompileWasmTemplatePlugin; @@ -79,7 +80,7 @@ class WebpackOptionsApply extends OptionsApply { let NodeTargetPlugin; let NodeTemplatePlugin; - switch(options.target) { + switch (options.target) { case "web": JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin"); FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin"); @@ -90,18 +91,17 @@ class WebpackOptionsApply extends OptionsApply { new NodeSourcePlugin(options.node).apply(compiler); new LoaderTargetPlugin(options.target).apply(compiler); break; - case "webworker": - { - let WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin"); - FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin"); - NodeSourcePlugin = require("./node/NodeSourcePlugin"); - new WebWorkerTemplatePlugin().apply(compiler); - new FetchCompileWasmTemplatePlugin(options.output).apply(compiler); - new FunctionModulePlugin(options.output).apply(compiler); - new NodeSourcePlugin(options.node).apply(compiler); - new LoaderTargetPlugin(options.target).apply(compiler); - break; - } + case "webworker": { + let WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin"); + FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin"); + NodeSourcePlugin = require("./node/NodeSourcePlugin"); + new WebWorkerTemplatePlugin().apply(compiler); + new FetchCompileWasmTemplatePlugin(options.output).apply(compiler); + new FunctionModulePlugin(options.output).apply(compiler); + new NodeSourcePlugin(options.node).apply(compiler); + new LoaderTargetPlugin(options.target).apply(compiler); + break; + } case "node": case "async-node": NodeTemplatePlugin = require("./node/NodeTemplatePlugin"); @@ -187,26 +187,39 @@ class WebpackOptionsApply extends OptionsApply { default: throw new Error("Unsupported target '" + options.target + "'."); } - } else if(options.target !== false) { + } else if (options.target !== false) { options.target(compiler); } else { throw new Error("Unsupported target '" + options.target + "'."); } - if(options.output.library || options.output.libraryTarget !== "var") { + if (options.output.library || options.output.libraryTarget !== "var") { let LibraryTemplatePlugin = require("./LibraryTemplatePlugin"); - new LibraryTemplatePlugin(options.output.library, options.output.libraryTarget, options.output.umdNamedDefine, options.output.auxiliaryComment || "", options.output.libraryExport).apply(compiler); + new LibraryTemplatePlugin( + options.output.library, + options.output.libraryTarget, + options.output.umdNamedDefine, + options.output.auxiliaryComment || "", + options.output.libraryExport + ).apply(compiler); } - if(options.externals) { + if (options.externals) { ExternalsPlugin = require("./ExternalsPlugin"); - new ExternalsPlugin(options.output.libraryTarget, options.externals).apply(compiler); + new ExternalsPlugin( + options.output.libraryTarget, + options.externals + ).apply(compiler); } let noSources; let legacy; let modern; let comment; - if(options.devtool && (options.devtool.includes("sourcemap") || options.devtool.includes("source-map"))) { + if ( + options.devtool && + (options.devtool.includes("sourcemap") || + options.devtool.includes("source-map")) + ) { const hidden = options.devtool.includes("hidden"); const inline = options.devtool.includes("inline"); const evalWrapped = options.devtool.includes("eval"); @@ -215,15 +228,22 @@ class WebpackOptionsApply extends OptionsApply { noSources = options.devtool.includes("nosources"); legacy = options.devtool.includes("@"); modern = options.devtool.includes("#"); - comment = legacy && modern ? "\n/*\n//@ source" + "MappingURL=[url]\n//# source" + "MappingURL=[url]\n*/" : - legacy ? "\n/*\n//@ source" + "MappingURL=[url]\n*/" : - modern ? "\n//# source" + "MappingURL=[url]" : - null; - let Plugin = evalWrapped ? EvalSourceMapDevToolPlugin : SourceMapDevToolPlugin; + comment = + legacy && modern + ? "\n/*\n//@ source" + + "MappingURL=[url]\n//# source" + + "MappingURL=[url]\n*/" + : legacy + ? "\n/*\n//@ source" + "MappingURL=[url]\n*/" + : modern ? "\n//# source" + "MappingURL=[url]" : null; + let Plugin = evalWrapped + ? EvalSourceMapDevToolPlugin + : SourceMapDevToolPlugin; new Plugin({ filename: inline ? null : options.output.sourceMapFilename, moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate, - fallbackModuleFilenameTemplate: options.output.devtoolFallbackModuleFilenameTemplate, + fallbackModuleFilenameTemplate: + options.output.devtoolFallbackModuleFilenameTemplate, append: hidden ? false : comment, module: moduleMaps ? true : cheap ? false : true, columns: cheap ? false : true, @@ -231,13 +251,15 @@ class WebpackOptionsApply extends OptionsApply { noSources: noSources, namespace: options.output.devtoolNamespace }).apply(compiler); - } else if(options.devtool && options.devtool.includes("eval")) { + } else if (options.devtool && options.devtool.includes("eval")) { legacy = options.devtool.includes("@"); modern = options.devtool.includes("#"); - comment = legacy && modern ? "\n//@ sourceURL=[url]\n//# sourceURL=[url]" : - legacy ? "\n//@ sourceURL=[url]" : - modern ? "\n//# sourceURL=[url]" : - null; + comment = + legacy && modern + ? "\n//@ sourceURL=[url]\n//# sourceURL=[url]" + : legacy + ? "\n//@ sourceURL=[url]" + : modern ? "\n//# sourceURL=[url]" : null; new EvalDevToolModulePlugin({ sourceUrlComment: comment, moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate, @@ -264,54 +286,58 @@ class WebpackOptionsApply extends OptionsApply { new UseStrictPlugin().apply(compiler); new RequireIncludePlugin().apply(compiler); new RequireEnsurePlugin().apply(compiler); - new RequireContextPlugin(options.resolve.modules, options.resolve.extensions, options.resolve.mainFiles).apply(compiler); + new RequireContextPlugin( + options.resolve.modules, + options.resolve.extensions, + options.resolve.mainFiles + ).apply(compiler); new ImportPlugin(options.module).apply(compiler); new SystemPlugin(options.module).apply(compiler); - if(typeof options.mode !== "string") + if (typeof options.mode !== "string") new WarnNoModeSetPlugin().apply(compiler); new EnsureChunkConditionsPlugin().apply(compiler); - if(options.optimization.removeAvailableModules) + if (options.optimization.removeAvailableModules) new RemoveParentModulesPlugin().apply(compiler); - if(options.optimization.removeEmptyChunks) + if (options.optimization.removeEmptyChunks) new RemoveEmptyChunksPlugin().apply(compiler); - if(options.optimization.mergeDuplicateChunks) + if (options.optimization.mergeDuplicateChunks) new MergeDuplicateChunksPlugin().apply(compiler); - if(options.optimization.flagIncludedChunks) + if (options.optimization.flagIncludedChunks) new FlagIncludedChunksPlugin().apply(compiler); - if(options.optimization.occurrenceOrder) + if (options.optimization.occurrenceOrder) new OccurrenceOrderPlugin(true).apply(compiler); - if(options.optimization.sideEffects) + if (options.optimization.sideEffects) new SideEffectsFlagPlugin().apply(compiler); - if(options.optimization.providedExports) + if (options.optimization.providedExports) new FlagDependencyExportsPlugin().apply(compiler); - if(options.optimization.usedExports) + if (options.optimization.usedExports) new FlagDependencyUsagePlugin().apply(compiler); - if(options.optimization.concatenateModules) + if (options.optimization.concatenateModules) new ModuleConcatenationPlugin().apply(compiler); - if(options.optimization.splitChunks) + if (options.optimization.splitChunks) new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler); - if(options.optimization.runtimeChunk) + if (options.optimization.runtimeChunk) new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler); - if(options.optimization.noEmitOnErrors) + if (options.optimization.noEmitOnErrors) new NoEmitOnErrorsPlugin().apply(compiler); - if(options.optimization.namedModules) + if (options.optimization.namedModules) new NamedModulesPlugin().apply(compiler); - if(options.optimization.namedChunks) + if (options.optimization.namedChunks) new NamedChunksPlugin().apply(compiler); - if(options.optimization.nodeEnv) { + if (options.optimization.nodeEnv) { new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv) }).apply(compiler); } - if(options.optimization.minimize) { - for(const minimizer of options.optimization.minimizer) { + if (options.optimization.minimize) { + for (const minimizer of options.optimization.minimizer) { minimizer.apply(compiler); } } - if(options.performance) { + if (options.performance) { new SizeLimitsPlugin(options.performance).apply(compiler); } @@ -323,29 +349,50 @@ class WebpackOptionsApply extends OptionsApply { new WarnCaseSensitiveModulesPlugin().apply(compiler); - if(options.cache) { + if (options.cache) { let CachePlugin = require("./CachePlugin"); - new CachePlugin(typeof options.cache === "object" ? options.cache : null).apply(compiler); + new CachePlugin( + typeof options.cache === "object" ? options.cache : null + ).apply(compiler); } compiler.hooks.afterPlugins.call(compiler); - if(!compiler.inputFileSystem) throw new Error("No input filesystem provided"); - compiler.resolverFactory.hooks.resolveOptions.for("normal").tap("WebpackOptionsApply", resolveOptions => { - return Object.assign({ - fileSystem: compiler.inputFileSystem - }, options.resolve, resolveOptions); - }); - compiler.resolverFactory.hooks.resolveOptions.for("context").tap("WebpackOptionsApply", resolveOptions => { - return Object.assign({ - fileSystem: compiler.inputFileSystem, - resolveToContext: true - }, options.resolve, resolveOptions); - }); - compiler.resolverFactory.hooks.resolveOptions.for("loader").tap("WebpackOptionsApply", resolveOptions => { - return Object.assign({ - fileSystem: compiler.inputFileSystem - }, options.resolveLoader, resolveOptions); - }); + if (!compiler.inputFileSystem) + throw new Error("No input filesystem provided"); + compiler.resolverFactory.hooks.resolveOptions + .for("normal") + .tap("WebpackOptionsApply", resolveOptions => { + return Object.assign( + { + fileSystem: compiler.inputFileSystem + }, + options.resolve, + resolveOptions + ); + }); + compiler.resolverFactory.hooks.resolveOptions + .for("context") + .tap("WebpackOptionsApply", resolveOptions => { + return Object.assign( + { + fileSystem: compiler.inputFileSystem, + resolveToContext: true + }, + options.resolve, + resolveOptions + ); + }); + compiler.resolverFactory.hooks.resolveOptions + .for("loader") + .tap("WebpackOptionsApply", resolveOptions => { + return Object.assign( + { + fileSystem: compiler.inputFileSystem + }, + options.resolveLoader, + resolveOptions + ); + }); compiler.hooks.afterResolvers.call(compiler); return options; } diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index 6de760604..3c7b1f83a 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -19,7 +19,11 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("entry", "./src"); - this.set("devtool", "make", options => (options.mode === "development" ? "eval" : false)); + this.set( + "devtool", + "make", + options => (options.mode === "development" ? "eval" : false) + ); this.set("cache", "make", options => options.mode === "development"); this.set("context", process.cwd()); @@ -41,7 +45,8 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("module.strictThisContextOnImports", false); this.set("module.unsafeCache", "make", options => !!options.cache); this.set("module.rules", []); - this.set("module.defaultRules", "make", options => [{ + this.set("module.defaultRules", "make", options => [ + { type: "javascript/auto", resolve: {} }, @@ -49,7 +54,10 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { test: /\.mjs$/i, type: "javascript/esm", resolve: { - mainFields: options.target === "web" || options.target === "webworker" ? ["browser", "main"] : ["main"] + mainFields: + options.target === "web" || options.target === "webworker" + ? ["browser", "main"] + : ["main"] } }, { @@ -63,11 +71,11 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { ]); this.set("output", "call", (value, options) => { - if(typeof value === "string") { + if (typeof value === "string") { return { filename: value }; - } else if(typeof value !== "object") { + } else if (typeof value !== "object") { return {}; } else { return Object.assign({}, value); @@ -77,28 +85,34 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("output.filename", "[name].js"); this.set("output.chunkFilename", "make", options => { const filename = options.output.filename; - if(typeof filename === "function") return filename; + if (typeof filename === "function") return filename; const hasName = filename.includes("[name]"); const hasId = filename.includes("[id]"); const hasChunkHash = filename.includes("[chunkhash]"); // Anything changing depending on chunk is fine - if(hasChunkHash || hasName || hasId) return filename; + if (hasChunkHash || hasName || hasId) return filename; // Elsewise prefix "[id]." in front of the basename to make it changing return filename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2"); }); this.set("output.webassemblyModuleFilename", "[modulehash].module.wasm"); this.set("output.library", ""); this.set("output.hotUpdateFunction", "make", options => { - return Template.toIdentifier("webpackHotUpdate" + Template.toIdentifier(options.output.library)); + return Template.toIdentifier( + "webpackHotUpdate" + Template.toIdentifier(options.output.library) + ); }); this.set("output.jsonpFunction", "make", options => { - return Template.toIdentifier("webpackJsonp" + Template.toIdentifier(options.output.library)); + return Template.toIdentifier( + "webpackJsonp" + Template.toIdentifier(options.output.library) + ); }); this.set("output.chunkCallbackName", "make", options => { - return Template.toIdentifier("webpackChunk" + Template.toIdentifier(options.output.library)); + return Template.toIdentifier( + "webpackChunk" + Template.toIdentifier(options.output.library) + ); }); this.set("output.globalObject", "make", options => { - switch(options.target) { + switch (options.target) { case "web": case "electron-renderer": return "window"; @@ -118,7 +132,11 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { }); this.set("output.libraryTarget", "var"); this.set("output.path", path.join(process.cwd(), "dist")); - this.set("output.pathinfo", "make", options => options.mode === "development"); + this.set( + "output.pathinfo", + "make", + options => options.mode === "development" + ); this.set("output.sourceMapFilename", "[file].map[query]"); this.set("output.hotUpdateChunkFilename", "[id].[hash].hot-update.js"); this.set("output.hotUpdateMainFilename", "[hash].hot-update.json"); @@ -132,7 +150,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("output.strictModuleExceptionHandling", false); this.set("node", "call", value => { - if(typeof value === "boolean") { + if (typeof value === "boolean") { return value; } else { return Object.assign({}, value); @@ -146,9 +164,13 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("node.__filename", "mock"); this.set("node.__dirname", "mock"); - this.set("performance", "make", options => (isProductionLikeMode(options) ? false : undefined)); + this.set( + "performance", + "make", + options => (isProductionLikeMode(options) ? false : undefined) + ); this.set("performance", "call", value => { - if(typeof value === "boolean") { + if (typeof value === "boolean") { return value; } else { return Object.assign({}, value); @@ -156,17 +178,31 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { }); this.set("performance.maxAssetSize", 250000); this.set("performance.maxEntrypointSize", 250000); - this.set("performance.hints", "make", options => (isProductionLikeMode(options) ? "warning" : false)); + this.set( + "performance.hints", + "make", + options => (isProductionLikeMode(options) ? "warning" : false) + ); this.set("optimization.removeAvailableModules", true); this.set("optimization.removeEmptyChunks", true); this.set("optimization.mergeDuplicateChunks", true); - this.set("optimization.flagIncludedChunks", "make", options => isProductionLikeMode(options)); - this.set("optimization.occurrenceOrder", "make", options => isProductionLikeMode(options)); - this.set("optimization.sideEffects", "make", options => isProductionLikeMode(options)); + this.set("optimization.flagIncludedChunks", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.occurrenceOrder", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.sideEffects", "make", options => + isProductionLikeMode(options) + ); this.set("optimization.providedExports", true); - this.set("optimization.usedExports", "make", options => isProductionLikeMode(options)); - this.set("optimization.concatenateModules", "make", options => isProductionLikeMode(options)); + this.set("optimization.usedExports", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.concatenateModules", "make", options => + isProductionLikeMode(options) + ); this.set("optimization.splitChunks", {}); this.set("optimization.splitChunks.chunks", "async"); this.set("optimization.splitChunks.minSize", 30000); @@ -185,35 +221,62 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { priority: -10 }); this.set("optimization.runtimeChunk", "call", value => { - if(value === "single") { + if (value === "single") { return { name: "runtime" }; } - if(value === true || value === "multiple") { + if (value === true || value === "multiple") { return { name: entrypoint => `runtime~${entrypoint.name}` }; } return value; }); - this.set("optimization.noEmitOnErrors", "make", options => isProductionLikeMode(options)); - this.set("optimization.namedModules", "make", options => options.mode === "development"); - this.set("optimization.namedChunks", "make", options => options.mode === "development"); - this.set("optimization.portableRecords", "make", options => !!(options.recordsInputPath || options.recordsOutputPath || options.recordsPath)); - this.set("optimization.minimize", "make", options => isProductionLikeMode(options)); - this.set("optimization.minimizer", "make", options => [{ - apply: compiler => { - // Lazy load the uglifyjs plugin - const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); - new UglifyJsPlugin({ - cache: true, - parallel: true, - sourceMap: options.devtool && /source-?map/.test(options.devtool) - }).apply(compiler); + this.set("optimization.noEmitOnErrors", "make", options => + isProductionLikeMode(options) + ); + this.set( + "optimization.namedModules", + "make", + options => options.mode === "development" + ); + this.set( + "optimization.namedChunks", + "make", + options => options.mode === "development" + ); + this.set( + "optimization.portableRecords", + "make", + options => + !!( + options.recordsInputPath || + options.recordsOutputPath || + options.recordsPath + ) + ); + this.set("optimization.minimize", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.minimizer", "make", options => [ + { + apply: compiler => { + // Lazy load the uglifyjs plugin + const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); + new UglifyJsPlugin({ + cache: true, + parallel: true, + sourceMap: options.devtool && /source-?map/.test(options.devtool) + }).apply(compiler); + } } - }]); - this.set("optimization.nodeEnv", "make", options => options.mode || "production"); + ]); + this.set( + "optimization.nodeEnv", + "make", + options => options.mode || "production" + ); this.set("resolve", "call", value => Object.assign({}, value)); this.set("resolve.unsafeCache", true); @@ -221,15 +284,20 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("resolve.extensions", [".wasm", ".mjs", ".js", ".json"]); this.set("resolve.mainFiles", ["index"]); this.set("resolve.aliasFields", "make", options => { - if(options.target === "web" || options.target === "webworker") return ["browser"]; + if (options.target === "web" || options.target === "webworker") + return ["browser"]; else return []; }); this.set("resolve.mainFields", "make", options => { - if(options.target === "web" || options.target === "webworker") return ["browser", "module", "main"]; + if (options.target === "web" || options.target === "webworker") + return ["browser", "module", "main"]; else return ["module", "main"]; }); this.set("resolve.cacheWithContext", "make", options => { - return Array.isArray(options.resolve.plugins) && options.resolve.plugins.length > 0; + return ( + Array.isArray(options.resolve.plugins) && + options.resolve.plugins.length > 0 + ); }); this.set("resolveLoader", "call", value => Object.assign({}, value)); @@ -238,7 +306,10 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("resolveLoader.extensions", [".js", ".json"]); this.set("resolveLoader.mainFiles", ["index"]); this.set("resolveLoader.cacheWithContext", "make", options => { - return Array.isArray(options.resolveLoader.plugins) && options.resolveLoader.plugins.length > 0; + return ( + Array.isArray(options.resolveLoader.plugins) && + options.resolveLoader.plugins.length > 0 + ); }); } } diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index 2886bce21..d2d59deeb 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -11,47 +11,48 @@ const getSchemaPart = (path, parents, additionalPath) => { parents = parents || 0; path = path.split("/"); path = path.slice(0, path.length - parents); - if(additionalPath) { + if (additionalPath) { additionalPath = additionalPath.split("/"); path = path.concat(additionalPath); } let schemaPart = webpackOptionsSchema; - for(let i = 1; i < path.length; i++) { + for (let i = 1; i < path.length; i++) { const inner = schemaPart[path[i]]; - if(inner) - schemaPart = inner; + if (inner) schemaPart = inner; } return schemaPart; }; const getSchemaPartText = (schemaPart, additionalPath) => { - if(additionalPath) { - for(let i = 0; i < additionalPath.length; i++) { + if (additionalPath) { + for (let i = 0; i < additionalPath.length; i++) { const inner = schemaPart[additionalPath[i]]; - if(inner) - schemaPart = inner; + if (inner) schemaPart = inner; } } - while(schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref); + while (schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref); let schemaText = WebpackOptionsValidationError.formatSchema(schemaPart); - if(schemaPart.description) - schemaText += `\n-> ${schemaPart.description}`; + if (schemaPart.description) schemaText += `\n-> ${schemaPart.description}`; return schemaText; }; const getSchemaPartDescription = schemaPart => { - while(schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref); - if(schemaPart.description) - return `\n-> ${schemaPart.description}`; + while (schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref); + if (schemaPart.description) return `\n-> ${schemaPart.description}`; return ""; }; const filterChildren = children => { - return children.filter(err => err.keyword !== "anyOf" && err.keyword !== "allOf" && err.keyword !== "oneOf"); + return children.filter( + err => + err.keyword !== "anyOf" && + err.keyword !== "allOf" && + err.keyword !== "oneOf" + ); }; const indent = (str, prefix, firstLine) => { - if(firstLine) { + if (firstLine) { return prefix + str.replace(/\n(?!$)/g, "\n" + prefix); } else { return str.replace(/\n(?!$)/g, `\n${prefix}`); @@ -63,9 +64,20 @@ class WebpackOptionsValidationError extends WebpackError { super(); this.name = "WebpackOptionsValidationError"; - this.message = "Invalid configuration object. " + + this.message = + "Invalid configuration object. " + "Webpack has been initialised using a configuration object that does not match the API schema.\n" + - validationErrors.map(err => " - " + indent(WebpackOptionsValidationError.formatValidationError(err), " ", false)).join("\n"); + validationErrors + .map( + err => + " - " + + indent( + WebpackOptionsValidationError.formatValidationError(err), + " ", + false + ) + ) + .join("\n"); this.validationErrors = validationErrors; Error.captureStackTrace(this, this.constructor); @@ -75,59 +87,74 @@ class WebpackOptionsValidationError extends WebpackError { prevSchemas = prevSchemas || []; const formatInnerSchema = (innerSchema, addSelf) => { - if(!addSelf) return WebpackOptionsValidationError.formatSchema(innerSchema, prevSchemas); - if(prevSchemas.includes(innerSchema)) return "(recursive)"; - return WebpackOptionsValidationError.formatSchema(innerSchema, prevSchemas.concat(schema)); + if (!addSelf) + return WebpackOptionsValidationError.formatSchema( + innerSchema, + prevSchemas + ); + if (prevSchemas.includes(innerSchema)) return "(recursive)"; + return WebpackOptionsValidationError.formatSchema( + innerSchema, + prevSchemas.concat(schema) + ); }; - if(schema.type === "string") { - if(schema.minLength === 1) - return "non-empty string"; - else if(schema.minLength > 1) + if (schema.type === "string") { + if (schema.minLength === 1) return "non-empty string"; + else if (schema.minLength > 1) return `string (min length ${schema.minLength})`; return "string"; - } else if(schema.type === "boolean") { + } else if (schema.type === "boolean") { return "boolean"; - } else if(schema.type === "number") { + } else if (schema.type === "number") { return "number"; - } else if(schema.type === "object") { - if(schema.properties) { + } else if (schema.type === "object") { + if (schema.properties) { const required = schema.required || []; - return `object { ${Object.keys(schema.properties).map(property => { - if(!required.includes(property)) return property + "?"; - return property; - }).concat(schema.additionalProperties ? ["..."] : []).join(", ")} }`; + return `object { ${Object.keys(schema.properties) + .map(property => { + if (!required.includes(property)) return property + "?"; + return property; + }) + .concat(schema.additionalProperties ? ["..."] : []) + .join(", ")} }`; } - if(schema.additionalProperties) { - return `object { : ${formatInnerSchema(schema.additionalProperties)} }`; + if (schema.additionalProperties) { + return `object { : ${formatInnerSchema( + schema.additionalProperties + )} }`; } return "object"; - } else if(schema.type === "array") { + } else if (schema.type === "array") { return `[${formatInnerSchema(schema.items)}]`; } - switch(schema.instanceof) { + switch (schema.instanceof) { case "Function": return "function"; case "RegExp": return "RegExp"; } - if(schema.$ref) return formatInnerSchema(getSchemaPart(schema.$ref), true); - if(schema.allOf) return schema.allOf.map(formatInnerSchema).join(" & "); - if(schema.oneOf) return schema.oneOf.map(formatInnerSchema).join(" | "); - if(schema.anyOf) return schema.anyOf.map(formatInnerSchema).join(" | "); - if(schema.enum) return schema.enum.map(item => JSON.stringify(item)).join(" | "); + if (schema.$ref) return formatInnerSchema(getSchemaPart(schema.$ref), true); + if (schema.allOf) return schema.allOf.map(formatInnerSchema).join(" & "); + if (schema.oneOf) return schema.oneOf.map(formatInnerSchema).join(" | "); + if (schema.anyOf) return schema.anyOf.map(formatInnerSchema).join(" | "); + if (schema.enum) + return schema.enum.map(item => JSON.stringify(item)).join(" | "); return JSON.stringify(schema, 0, 2); } static formatValidationError(err) { const dataPath = `configuration${err.dataPath}`; - if(err.keyword === "additionalProperties") { - const baseMessage = `${dataPath} has an unknown property '${err.params.additionalProperty}'. These properties are valid:\n${getSchemaPartText(err.parentSchema)}`; - if(!err.dataPath) { - switch(err.params.additionalProperty) { + if (err.keyword === "additionalProperties") { + const baseMessage = `${dataPath} has an unknown property '${ + err.params.additionalProperty + }'. These properties are valid:\n${getSchemaPartText(err.parentSchema)}`; + if (!err.dataPath) { + switch (err.params.additionalProperty) { case "debug": - return `${baseMessage}\n` + + return ( + `${baseMessage}\n` + "The 'debug' property was removed in webpack 2.\n" + "Loaders should be updated to allow passing this option via loader options in module.rules.\n" + "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" + @@ -135,9 +162,12 @@ class WebpackOptionsValidationError extends WebpackError { " new webpack.LoaderOptionsPlugin({\n" + " debug: true\n" + " })\n" + - "]"; + "]" + ); } - return baseMessage + "\n" + + return ( + baseMessage + + "\n" + "For typos: please correct them.\n" + "For loader options: webpack 2 no longer allows custom properties in configuration.\n" + " Loaders should be updated to allow passing options via loader options in module.rules.\n" + @@ -149,69 +179,139 @@ class WebpackOptionsValidationError extends WebpackError { ` ${err.params.additionalProperty}: ...\n` + " }\n" + " })\n" + - " ]"; + " ]" + ); } return baseMessage; - } else if(err.keyword === "oneOf" || err.keyword === "anyOf") { - if(err.children && err.children.length > 0) { - if(err.schema.length === 1) { + } else if (err.keyword === "oneOf" || err.keyword === "anyOf") { + if (err.children && err.children.length > 0) { + if (err.schema.length === 1) { const lastChild = err.children[err.children.length - 1]; - const remainingChildren = err.children.slice(0, err.children.length - 1); - return WebpackOptionsValidationError.formatValidationError(Object.assign({}, lastChild, { - children: remainingChildren, - parentSchema: Object.assign({}, err.parentSchema, lastChild.parentSchema) - })); + const remainingChildren = err.children.slice( + 0, + err.children.length - 1 + ); + return WebpackOptionsValidationError.formatValidationError( + Object.assign({}, lastChild, { + children: remainingChildren, + parentSchema: Object.assign( + {}, + err.parentSchema, + lastChild.parentSchema + ) + }) + ); } - return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}\n` + - `Details:\n${filterChildren(err.children).map(err => " * " + indent(WebpackOptionsValidationError.formatValidationError(err), " ", false)).join("\n")}`; + return ( + `${dataPath} should be one of these:\n${getSchemaPartText( + err.parentSchema + )}\n` + + `Details:\n${filterChildren(err.children) + .map( + err => + " * " + + indent( + WebpackOptionsValidationError.formatValidationError(err), + " ", + false + ) + ) + .join("\n")}` + ); } - return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}`; - - } else if(err.keyword === "enum") { - if(err.parentSchema && err.parentSchema.enum && err.parentSchema.enum.length === 1) { + return `${dataPath} should be one of these:\n${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "enum") { + if ( + err.parentSchema && + err.parentSchema.enum && + err.parentSchema.enum.length === 1 + ) { return `${dataPath} should be ${getSchemaPartText(err.parentSchema)}`; } - return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "allOf") { + return `${dataPath} should be one of these:\n${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "allOf") { return `${dataPath} should be:\n${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "type") { - switch(err.params.type) { + } else if (err.keyword === "type") { + switch (err.params.type) { case "object": - return `${dataPath} should be an object.${getSchemaPartDescription(err.parentSchema)}`; + return `${dataPath} should be an object.${getSchemaPartDescription( + err.parentSchema + )}`; case "string": - return `${dataPath} should be a string.${getSchemaPartDescription(err.parentSchema)}`; + return `${dataPath} should be a string.${getSchemaPartDescription( + err.parentSchema + )}`; case "boolean": - return `${dataPath} should be a boolean.${getSchemaPartDescription(err.parentSchema)}`; + return `${dataPath} should be a boolean.${getSchemaPartDescription( + err.parentSchema + )}`; case "number": - return `${dataPath} should be a number.${getSchemaPartDescription(err.parentSchema)}`; + return `${dataPath} should be a number.${getSchemaPartDescription( + err.parentSchema + )}`; case "array": - return `${dataPath} should be an array:\n${getSchemaPartText(err.parentSchema)}`; + return `${dataPath} should be an array:\n${getSchemaPartText( + err.parentSchema + )}`; } - return `${dataPath} should be ${err.params.type}:\n${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "instanceof") { - return `${dataPath} should be an instance of ${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "required") { + return `${dataPath} should be ${err.params.type}:\n${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "instanceof") { + return `${dataPath} should be an instance of ${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "required") { const missingProperty = err.params.missingProperty.replace(/^\./, ""); - return `${dataPath} misses the property '${missingProperty}'.\n${getSchemaPartText(err.parentSchema, ["properties", missingProperty])}`; - } else if(err.keyword === "minimum") { - return `${dataPath} ${err.message}.${getSchemaPartDescription(err.parentSchema)}`; - } else if(err.keyword === "uniqueItems") { - return `${dataPath} should not contain the item '${err.data[err.params.i]}' twice.${getSchemaPartDescription(err.parentSchema)}`; - } else if(err.keyword === "minLength" || err.keyword === "minItems" || err.keyword === "minProperties") { - if(err.params.limit === 1) - return `${dataPath} should not be empty.${getSchemaPartDescription(err.parentSchema)}`; + return `${dataPath} misses the property '${ + missingProperty + }'.\n${getSchemaPartText(err.parentSchema, [ + "properties", + missingProperty + ])}`; + } else if (err.keyword === "minimum") { + return `${dataPath} ${err.message}.${getSchemaPartDescription( + err.parentSchema + )}`; + } else if (err.keyword === "uniqueItems") { + return `${dataPath} should not contain the item '${ + err.data[err.params.i] + }' twice.${getSchemaPartDescription(err.parentSchema)}`; + } else if ( + err.keyword === "minLength" || + err.keyword === "minItems" || + err.keyword === "minProperties" + ) { + if (err.params.limit === 1) + return `${dataPath} should not be empty.${getSchemaPartDescription( + err.parentSchema + )}`; else - return `${dataPath} ${err.message}${getSchemaPartDescription(err.parentSchema)}`; - } else if(err.keyword === "absolutePath") { - const baseMessage = `${dataPath}: ${err.message}${getSchemaPartDescription(err.parentSchema)}`; - if(dataPath === "configuration.output.filename") { - return `${baseMessage}\n` + - "Please use output.path to specify absolute path and output.filename for the file name."; + return `${dataPath} ${err.message}${getSchemaPartDescription( + err.parentSchema + )}`; + } else if (err.keyword === "absolutePath") { + const baseMessage = `${dataPath}: ${ + err.message + }${getSchemaPartDescription(err.parentSchema)}`; + if (dataPath === "configuration.output.filename") { + return ( + `${baseMessage}\n` + + "Please use output.path to specify absolute path and output.filename for the file name." + ); } return baseMessage; } else { // eslint-disable-line no-fallthrough - return `${dataPath} ${err.message} (${JSON.stringify(err, 0, 2)}).\n${getSchemaPartText(err.parentSchema)}`; + return `${dataPath} ${err.message} (${JSON.stringify( + err, + 0, + 2 + )}).\n${getSchemaPartText(err.parentSchema)}`; } } } diff --git a/lib/compareLocations.js b/lib/compareLocations.js index f4ccb1aef..51227f254 100644 --- a/lib/compareLocations.js +++ b/lib/compareLocations.js @@ -4,30 +4,30 @@ */ "use strict"; module.exports = (a, b) => { - if(typeof a === "string") { - if(typeof b === "string") { - if(a < b) return -1; - if(a > b) return 1; + if (typeof a === "string") { + if (typeof b === "string") { + if (a < b) return -1; + if (a > b) return 1; return 0; - } else if(typeof b === "object") { + } else if (typeof b === "object") { return 1; } else { return 0; } - } else if(typeof a === "object") { - if(typeof b === "string") { + } else if (typeof a === "object") { + if (typeof b === "string") { return -1; - } else if(typeof b === "object") { - if(a.start && b.start) { + } else if (typeof b === "object") { + if (a.start && b.start) { const ap = a.start; const bp = b.start; - if(ap.line < bp.line) return -1; - if(ap.line > bp.line) return 1; - if(ap.column < bp.column) return -1; - if(ap.column > bp.column) return 1; + if (ap.line < bp.line) return -1; + if (ap.line > bp.line) return 1; + if (ap.column < bp.column) return -1; + if (ap.column > bp.column) return 1; } - if(a.index < b.index) return -1; - if(a.index > b.index) return 1; + if (a.index < b.index) return -1; + if (a.index > b.index) return 1; return 0; } else { return 0; diff --git a/lib/debug/ProfilingPlugin.js b/lib/debug/ProfilingPlugin.js index a563e1a98..ea63513eb 100644 --- a/lib/debug/ProfilingPlugin.js +++ b/lib/debug/ProfilingPlugin.js @@ -6,7 +6,7 @@ let inspector = undefined; try { inspector = require("inspector"); // eslint-disable-line node/no-missing-require -} catch(e) { +} catch (e) { console.log("Unable to CPU profile in < node 8.0"); } @@ -21,14 +21,14 @@ class Profiler { } startProfiling() { - if(this.inspector === undefined) { + if (this.inspector === undefined) { return Promise.resolve(); } try { this.session = new inspector.Session(); this.session.connect(); - } catch(_) { + } catch (_) { this.session = undefined; return Promise.resolve(); } @@ -38,15 +38,15 @@ class Profiler { interval: 100 }), this.sendCommand("Profiler.enable"), - this.sendCommand("Profiler.start"), + this.sendCommand("Profiler.start") ]); } sendCommand(method, params) { - if(this.hasSession()) { + if (this.hasSession()) { return new Promise((res, rej) => { return this.session.post(method, params, (err, params) => { - if(err !== null) { + if (err !== null) { rej(err); } else { res(params); @@ -59,7 +59,7 @@ class Profiler { } destroy() { - if(this.hasSession()) { + if (this.hasSession()) { this.session.disconnect(); } @@ -94,11 +94,13 @@ function createTrace(outputPath) { data: { sessionId: "-1", page: "0xfff", - frames: [{ - frame: "0xfff", - url: "webpack", - name: "" - }] + frames: [ + { + frame: "0xfff", + url: "webpack", + name: "" + } + ] } } }); @@ -110,7 +112,7 @@ function createTrace(outputPath) { args: { data: { sessionId: "-1" - }, + } } }); @@ -136,83 +138,97 @@ class ProfilingPlugin { // Compiler Hooks Object.keys(compiler.hooks).forEach(hookName => { - compiler.hooks[hookName].intercept(makeInterceptorFor("Compiler", tracer)(hookName)); + compiler.hooks[hookName].intercept( + makeInterceptorFor("Compiler", tracer)(hookName) + ); }); Object.keys(compiler.resolverFactory.hooks).forEach(hookName => { - compiler.resolverFactory.hooks[hookName].intercept(makeInterceptorFor("Resolver", tracer)(hookName)); + compiler.resolverFactory.hooks[hookName].intercept( + makeInterceptorFor("Resolver", tracer)(hookName) + ); }); - compiler.hooks.compilation.tap(pluginName, (compilation, { - normalModuleFactory, - contextModuleFactory - }) => { - interceptAllHooksFor(compilation, tracer, "Compilation"); - interceptAllHooksFor(normalModuleFactory, tracer, "Normal Module Factory"); - interceptAllHooksFor(contextModuleFactory, tracer, "Context Module Factory"); - interceptAllParserHooks(normalModuleFactory, tracer); - interceptTemplateInstancesFrom(compilation, tracer); - }); + compiler.hooks.compilation.tap( + pluginName, + (compilation, { normalModuleFactory, contextModuleFactory }) => { + interceptAllHooksFor(compilation, tracer, "Compilation"); + interceptAllHooksFor( + normalModuleFactory, + tracer, + "Normal Module Factory" + ); + interceptAllHooksFor( + contextModuleFactory, + tracer, + "Context Module Factory" + ); + interceptAllParserHooks(normalModuleFactory, tracer); + interceptTemplateInstancesFrom(compilation, tracer); + } + ); // We need to write out the CPU profile when we are all done. - compiler.hooks.done.tap({ - name: pluginName, - stage: Infinity - }, () => { - tracer.profiler.stopProfiling().then((parsedResults) => { + compiler.hooks.done.tap( + { + name: pluginName, + stage: Infinity + }, + () => { + tracer.profiler.stopProfiling().then(parsedResults => { + if (parsedResults === undefined) { + tracer.profiler.destroy(); + tracer.trace.flush(); + return; + } + + const cpuStartTime = parsedResults.profile.startTime; + const cpuEndTime = parsedResults.profile.endTime; + + tracer.trace.completeEvent({ + name: "TaskQueueManager::ProcessTaskFromWorkQueue", + id: ++tracer.counter, + cat: ["toplevel"], + ts: cpuStartTime, + args: { + src_file: "../../ipc/ipc_moji_bootstrap.cc", + src_func: "Accept" + } + }); + + tracer.trace.completeEvent({ + name: "EvaluateScript", + id: ++tracer.counter, + cat: ["devtools.timeline"], + ts: cpuStartTime, + dur: cpuEndTime - cpuStartTime, + args: { + data: { + url: "webpack", + lineNumber: 1, + columnNumber: 1, + frame: "0xFFF" + } + } + }); + + tracer.trace.instantEvent({ + name: "CpuProfile", + id: ++tracer.counter, + cat: ["disabled-by-default-devtools.timeline"], + ts: cpuEndTime, + args: { + data: { + cpuProfile: parsedResults.profile + } + } + }); - if(parsedResults === undefined) { tracer.profiler.destroy(); tracer.trace.flush(); - return; - } - - const cpuStartTime = parsedResults.profile.startTime; - const cpuEndTime = parsedResults.profile.endTime; - - tracer.trace.completeEvent({ - name: "TaskQueueManager::ProcessTaskFromWorkQueue", - id: ++tracer.counter, - cat: ["toplevel"], - ts: cpuStartTime, - args: { - src_file: "../../ipc/ipc_moji_bootstrap.cc", - src_func: "Accept" - } }); - - tracer.trace.completeEvent({ - name: "EvaluateScript", - id: ++tracer.counter, - cat: ["devtools.timeline"], - ts: cpuStartTime, - dur: cpuEndTime - cpuStartTime, - args: { - data: { - url: "webpack", - lineNumber: 1, - columnNumber: 1, - frame: "0xFFF" - } - } - }); - - tracer.trace.instantEvent({ - name: "CpuProfile", - id: ++tracer.counter, - cat: ["disabled-by-default-devtools.timeline"], - ts: cpuEndTime, - args: { - data: { - cpuProfile: parsedResults.profile - } - } - }); - - tracer.profiler.destroy(); - tracer.trace.flush(); - }); - }); + } + ); } } @@ -224,12 +240,10 @@ const interceptTemplateInstancesFrom = (compilation, tracer) => { moduleTemplates } = compilation; - const { - javascript, - webassembly - } = moduleTemplates; + const { javascript, webassembly } = moduleTemplates; - [{ + [ + { instance: mainTemplate, name: "MainTemplate" }, @@ -251,15 +265,19 @@ const interceptTemplateInstancesFrom = (compilation, tracer) => { } ].forEach(templateObject => { Object.keys(templateObject.instance.hooks).forEach(hookName => { - templateObject.instance.hooks[hookName].intercept(makeInterceptorFor(templateObject.name, tracer)(hookName)); + templateObject.instance.hooks[hookName].intercept( + makeInterceptorFor(templateObject.name, tracer)(hookName) + ); }); }); }; const interceptAllHooksFor = (instance, tracer, logLabel) => { - if(Reflect.has(instance, "hooks")) { + if (Reflect.has(instance, "hooks")) { Object.keys(instance.hooks).forEach(hookName => { - instance.hooks[hookName].intercept(makeInterceptorFor(logLabel, tracer)(hookName)); + instance.hooks[hookName].intercept( + makeInterceptorFor(logLabel, tracer)(hookName) + ); }); } }; @@ -274,28 +292,27 @@ const interceptAllParserHooks = (moduleFactory, tracer) => { ]; moduleTypes.forEach(moduleType => { - moduleFactory.hooks.parser.for(moduleType).tap("ProfilingPlugin", (parser, parserOpts) => { - interceptAllHooksFor(parser, tracer, "Parser"); - }); + moduleFactory.hooks.parser + .for(moduleType) + .tap("ProfilingPlugin", (parser, parserOpts) => { + interceptAllHooksFor(parser, tracer, "Parser"); + }); }); }; -const makeInterceptorFor = (instance, tracer) => (hookName) => ({ - register: ({ - name, - type, - fn - }) => { +const makeInterceptorFor = (instance, tracer) => hookName => ({ + register: ({ name, type, fn }) => { const newFn = makeNewProfiledTapFn(hookName, tracer, { name, type, fn }); - return({ // eslint-disable-line + return { + // eslint-disable-line name, type, fn: newFn - }); + }; } }); @@ -305,16 +322,13 @@ const makeInterceptorFor = (instance, tracer) => (hookName) => ({ * @param {{name: string, type: string, fn: Function}} opts Options for the profiled fn. * @returns {*} Chainable hooked function. */ -const makeNewProfiledTapFn = (hookName, tracer, { - name, - type, - fn -}) => { +const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => { const defaultCategory = ["blink.user_timing"]; - switch(type) { + switch (type) { case "promise": - return(...args) => { // eslint-disable-line + return (...args) => { + // eslint-disable-line const id = ++tracer.counter; tracer.trace.begin({ name, @@ -331,7 +345,8 @@ const makeNewProfiledTapFn = (hookName, tracer, { }); }; case "async": - return(...args) => { // eslint-disable-line + return (...args) => { + // eslint-disable-line const id = ++tracer.counter; tracer.trace.begin({ name, @@ -349,11 +364,12 @@ const makeNewProfiledTapFn = (hookName, tracer, { }); }; case "sync": - return(...args) => { // eslint-disable-line + return (...args) => { + // eslint-disable-line const id = ++tracer.counter; // Do not instrument outself due to the CPU // profile needing to be the last event in the trace. - if(name === pluginName) { + if (name === pluginName) { return fn(...args); } @@ -365,7 +381,7 @@ const makeNewProfiledTapFn = (hookName, tracer, { let r; try { r = fn(...args); - } catch(error) { + } catch (error) { tracer.trace.end({ name, id, diff --git a/lib/dependencies/AMDDefineDependency.js b/lib/dependencies/AMDDefineDependency.js index 850fa3c7e..66539e539 100644 --- a/lib/dependencies/AMDDefineDependency.js +++ b/lib/dependencies/AMDDefineDependency.js @@ -28,10 +28,7 @@ AMDDefineDependency.Template = class AMDDefineDependencyTemplate { `!(__WEBPACK_AMD_DEFINE_RESULT__ = (#).call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` ], - o: [ - "", - "!(module.exports = #)" - ], + o: ["", "!(module.exports = #)"], of: [ "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;", `!(__WEBPACK_AMD_DEFINE_FACTORY__ = (#), @@ -45,10 +42,7 @@ AMDDefineDependency.Template = class AMDDefineDependencyTemplate { `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_RESULT__ = (#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` ], - ao: [ - "", - "!(#, module.exports = #)" - ], + ao: ["", "!(#, module.exports = #)"], aof: [ "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;", `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), @@ -60,10 +54,7 @@ AMDDefineDependency.Template = class AMDDefineDependencyTemplate { "var XXX, XXXmodule;", "!(XXXmodule = { id: YYY, exports: {}, loaded: false }, XXX = #.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule), XXXmodule.loaded = true, XXX === undefined && (XXX = XXXmodule.exports))" ], - lo: [ - "var XXX;", - "!(XXX = #)" - ], + lo: ["var XXX;", "!(XXX = #)"], lof: [ "var XXX, XXXfactory, XXXmodule;", "!(XXXfactory = (#), (XXXmodule = { id: YYY, exports: {}, loaded: false }), XXX = (typeof XXXfactory === 'function' ? (XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)) : XXXfactory), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports))" @@ -72,10 +63,7 @@ AMDDefineDependency.Template = class AMDDefineDependencyTemplate { "var __WEBPACK_AMD_DEFINE_ARRAY__, XXX;", "!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, XXX = ((#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)))" ], - lao: [ - "var XXX;", - "!(#, XXX = #)" - ], + lao: ["var XXX;", "!(#, XXX = #)"], laof: [ "var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, XXX;", `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), @@ -94,7 +82,11 @@ AMDDefineDependency.Template = class AMDDefineDependencyTemplate { } localModuleVar(dependency) { - return dependency.localModule && dependency.localModule.used && dependency.localModule.variableName(); + return ( + dependency.localModule && + dependency.localModule.used && + dependency.localModule.variableName() + ); } branch(dependency) { @@ -107,35 +99,37 @@ AMDDefineDependency.Template = class AMDDefineDependencyTemplate { replace(dependency, source, definition, text) { const localModuleVar = this.localModuleVar(dependency); - if(localModuleVar) { + if (localModuleVar) { text = text.replace(/XXX/g, localModuleVar.replace(/\$/g, "$$$$")); - definition = definition.replace(/XXX/g, localModuleVar.replace(/\$/g, "$$$$")); + definition = definition.replace( + /XXX/g, + localModuleVar.replace(/\$/g, "$$$$") + ); } - if(dependency.namedModule) { + if (dependency.namedModule) { text = text.replace(/YYY/g, JSON.stringify(dependency.namedModule)); } const texts = text.split("#"); - if(definition) source.insert(0, definition); + if (definition) source.insert(0, definition); let current = dependency.range[0]; - if(dependency.arrayRange) { + if (dependency.arrayRange) { source.replace(current, dependency.arrayRange[0] - 1, texts.shift()); current = dependency.arrayRange[1]; } - if(dependency.objectRange) { + if (dependency.objectRange) { source.replace(current, dependency.objectRange[0] - 1, texts.shift()); current = dependency.objectRange[1]; - } else if(dependency.functionRange) { + } else if (dependency.functionRange) { source.replace(current, dependency.functionRange[0] - 1, texts.shift()); current = dependency.functionRange[1]; } source.replace(current, dependency.range[1] - 1, texts.shift()); - if(texts.length > 0) - throw new Error("Implementation error"); + if (texts.length > 0) throw new Error("Implementation error"); } }; diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js index 0c6079994..c6959acd3 100644 --- a/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -14,24 +14,24 @@ const ContextDependencyHelpers = require("./ContextDependencyHelpers"); const LocalModulesHelpers = require("./LocalModulesHelpers"); const isBoundFunctionExpression = expr => { - if(expr.type !== "CallExpression") return false; - if(expr.callee.type !== "MemberExpression") return false; - if(expr.callee.computed) return false; - if(expr.callee.object.type !== "FunctionExpression") return false; - if(expr.callee.property.type !== "Identifier") return false; - if(expr.callee.property.name !== "bind") return false; + if (expr.type !== "CallExpression") return false; + if (expr.callee.type !== "MemberExpression") return false; + if (expr.callee.computed) return false; + if (expr.callee.object.type !== "FunctionExpression") return false; + if (expr.callee.property.type !== "Identifier") return false; + if (expr.callee.property.name !== "bind") return false; return true; }; function isUnboundFunctionExpression(expr) { - if(expr.type === "FunctionExpression") return true; - if(expr.type === "ArrowFunctionExpression") return true; + if (expr.type === "FunctionExpression") return true; + if (expr.type === "ArrowFunctionExpression") return true; return false; } function isCallable(expr) { - if(isUnboundFunctionExpression(expr)) return true; - if(isBoundFunctionExpression(expr)) return true; + if (isUnboundFunctionExpression(expr)) return true; + if (isBoundFunctionExpression(expr)) return true; return false; } @@ -40,36 +40,57 @@ class AMDDefineDependencyParserPlugin { this.options = options; } - newDefineDependency(range, arrayRange, functionRange, objectRange, namedModule) { - return new AMDDefineDependency(range, arrayRange, functionRange, objectRange, namedModule); + newDefineDependency( + range, + arrayRange, + functionRange, + objectRange, + namedModule + ) { + return new AMDDefineDependency( + range, + arrayRange, + functionRange, + objectRange, + namedModule + ); } apply(parser) { const options = this.options; const processArray = (expr, param, identifiers, namedModule) => { - if(param.isArray()) { + if (param.isArray()) { param.items.forEach((param, idx) => { - if(param.isString() && ["require", "module", "exports"].includes(param.string)) + if ( + param.isString() && + ["require", "module", "exports"].includes(param.string) + ) identifiers[idx] = param.string; const result = processItem(expr, param, namedModule); - if(result === undefined) { + if (result === undefined) { processContext(expr, param); } }); return true; - } else if(param.isConstArray()) { + } else if (param.isConstArray()) { const deps = []; param.array.forEach((request, idx) => { let dep; let localModule; - if(request === "require") { + if (request === "require") { identifiers[idx] = request; dep = "__webpack_require__"; - } else if(["exports", "module"].includes(request)) { + } else if (["exports", "module"].includes(request)) { identifiers[idx] = request; dep = request; - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, request)) { // eslint-disable-line no-cond-assign + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + request + )) + ) { + // eslint-disable-line no-cond-assign dep = new LocalModuleDependency(localModule); dep.loc = expr.loc; parser.state.current.addDependency(dep); @@ -89,21 +110,28 @@ class AMDDefineDependencyParserPlugin { } }; const processItem = (expr, param, namedModule) => { - if(param.isConditional()) { - param.options.forEach((param) => { + if (param.isConditional()) { + param.options.forEach(param => { const result = processItem(expr, param); - if(result === undefined) { + if (result === undefined) { processContext(expr, param); } }); return true; - } else if(param.isString()) { + } else if (param.isString()) { let dep, localModule; - if(param.string === "require") { + if (param.string === "require") { dep = new ConstDependency("__webpack_require__", param.range); - } else if(["require", "exports", "module"].includes(param.string)) { + } else if (["require", "exports", "module"].includes(param.string)) { dep = new ConstDependency(param.string, param.range); - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string, namedModule)) { // eslint-disable-line no-cond-assign + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string, + namedModule + )) + ) { + // eslint-disable-line no-cond-assign dep = new LocalModuleDependency(localModule, param.range); } else { dep = new AMDRequireItemDependency(param.string, param.range); @@ -115,154 +143,169 @@ class AMDDefineDependencyParserPlugin { } }; const processContext = (expr, param) => { - const dep = ContextDependencyHelpers.create(AMDRequireContextDependency, param.range, param, expr, options); - if(!dep) return; + const dep = ContextDependencyHelpers.create( + AMDRequireContextDependency, + param.range, + param, + expr, + options + ); + if (!dep) return; dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); return true; }; - parser.hooks.call.for("define").tap("AMDDefineDependencyParserPlugin", (expr) => { - let array, fn, obj, namedModule; - switch(expr.arguments.length) { - case 1: - if(isCallable(expr.arguments[0])) { - // define(f() {...}) - fn = expr.arguments[0]; - } else if(expr.arguments[0].type === "ObjectExpression") { - // define({...}) - obj = expr.arguments[0]; - } else { - // define(expr) - // unclear if function or object - obj = fn = expr.arguments[0]; - } - break; - case 2: - if(expr.arguments[0].type === "Literal") { + parser.hooks.call + .for("define") + .tap("AMDDefineDependencyParserPlugin", expr => { + let array, fn, obj, namedModule; + switch (expr.arguments.length) { + case 1: + if (isCallable(expr.arguments[0])) { + // define(f() {...}) + fn = expr.arguments[0]; + } else if (expr.arguments[0].type === "ObjectExpression") { + // define({...}) + obj = expr.arguments[0]; + } else { + // define(expr) + // unclear if function or object + obj = fn = expr.arguments[0]; + } + break; + case 2: + if (expr.arguments[0].type === "Literal") { + namedModule = expr.arguments[0].value; + // define("...", ...) + if (isCallable(expr.arguments[1])) { + // define("...", f() {...}) + fn = expr.arguments[1]; + } else if (expr.arguments[1].type === "ObjectExpression") { + // define("...", {...}) + obj = expr.arguments[1]; + } else { + // define("...", expr) + // unclear if function or object + obj = fn = expr.arguments[1]; + } + } else { + array = expr.arguments[0]; + if (isCallable(expr.arguments[1])) { + // define([...], f() {}) + fn = expr.arguments[1]; + } else if (expr.arguments[1].type === "ObjectExpression") { + // define([...], {...}) + obj = expr.arguments[1]; + } else { + // define([...], expr) + // unclear if function or object + obj = fn = expr.arguments[1]; + } + } + break; + case 3: + // define("...", [...], f() {...}) namedModule = expr.arguments[0].value; - // define("...", ...) - if(isCallable(expr.arguments[1])) { - // define("...", f() {...}) - fn = expr.arguments[1]; - } else if(expr.arguments[1].type === "ObjectExpression") { - // define("...", {...}) - obj = expr.arguments[1]; + array = expr.arguments[1]; + if (isCallable(expr.arguments[2])) { + // define("...", [...], f() {}) + fn = expr.arguments[2]; + } else if (expr.arguments[2].type === "ObjectExpression") { + // define("...", [...], {...}) + obj = expr.arguments[2]; } else { - // define("...", expr) + // define("...", [...], expr) // unclear if function or object - obj = fn = expr.arguments[1]; + obj = fn = expr.arguments[2]; } - } else { - array = expr.arguments[0]; - if(isCallable(expr.arguments[1])) { - // define([...], f() {}) - fn = expr.arguments[1]; - } else if(expr.arguments[1].type === "ObjectExpression") { - // define([...], {...}) - obj = expr.arguments[1]; - } else { - // define([...], expr) - // unclear if function or object - obj = fn = expr.arguments[1]; - } - } - break; - case 3: - // define("...", [...], f() {...}) - namedModule = expr.arguments[0].value; - array = expr.arguments[1]; - if(isCallable(expr.arguments[2])) { - // define("...", [...], f() {}) - fn = expr.arguments[2]; - } else if(expr.arguments[2].type === "ObjectExpression") { - // define("...", [...], {...}) - obj = expr.arguments[2]; - } else { - // define("...", [...], expr) - // unclear if function or object - obj = fn = expr.arguments[2]; - } - break; - default: - return; - } - let fnParams = null; - let fnParamsOffset = 0; - if(fn) { - if(isUnboundFunctionExpression(fn)) fnParams = fn.params; - else if(isBoundFunctionExpression(fn)) { - fnParams = fn.callee.object.params; - fnParamsOffset = fn.arguments.length - 1; - if(fnParamsOffset < 0) fnParamsOffset = 0; + break; + default: + return; } - } - let fnRenames = parser.scope.renames.createChild(); - let identifiers; - if(array) { - identifiers = {}; - const param = parser.evaluateExpression(array); - const result = processArray(expr, param, identifiers, namedModule); - if(!result) return; - if(fnParams) fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { - if(identifiers[idx]) { - fnRenames.set(param.name, identifiers[idx]); - return false; + let fnParams = null; + let fnParamsOffset = 0; + if (fn) { + if (isUnboundFunctionExpression(fn)) fnParams = fn.params; + else if (isBoundFunctionExpression(fn)) { + fnParams = fn.callee.object.params; + fnParamsOffset = fn.arguments.length - 1; + if (fnParamsOffset < 0) fnParamsOffset = 0; } - return true; - }); - } else { - identifiers = ["require", "exports", "module"]; - if(fnParams) fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { - if(identifiers[idx]) { - fnRenames.set(param.name, identifiers[idx]); - return false; - } - return true; - }); - } - let inTry; - if(fn && isUnboundFunctionExpression(fn)) { - inTry = parser.scope.inTry; - parser.inScope(fnParams, () => { - parser.scope.renames = fnRenames; - parser.scope.inTry = inTry; - if(fn.body.type === "BlockStatement") - parser.walkStatement(fn.body); - else - parser.walkExpression(fn.body); - }); - } else if(fn && isBoundFunctionExpression(fn)) { - inTry = parser.scope.inTry; - parser.inScope(fn.callee.object.params.filter((i) => !["require", "module", "exports"].includes(i.name)), () => { - parser.scope.renames = fnRenames; - parser.scope.inTry = inTry; - if(fn.callee.object.body.type === "BlockStatement") - parser.walkStatement(fn.callee.object.body); - else - parser.walkExpression(fn.callee.object.body); - }); - if(fn.arguments) - parser.walkExpressions(fn.arguments); - } else if(fn || obj) { - parser.walkExpression(fn || obj); - } + } + let fnRenames = parser.scope.renames.createChild(); + let identifiers; + if (array) { + identifiers = {}; + const param = parser.evaluateExpression(array); + const result = processArray(expr, param, identifiers, namedModule); + if (!result) return; + if (fnParams) + fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { + if (identifiers[idx]) { + fnRenames.set(param.name, identifiers[idx]); + return false; + } + return true; + }); + } else { + identifiers = ["require", "exports", "module"]; + if (fnParams) + fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { + if (identifiers[idx]) { + fnRenames.set(param.name, identifiers[idx]); + return false; + } + return true; + }); + } + let inTry; + if (fn && isUnboundFunctionExpression(fn)) { + inTry = parser.scope.inTry; + parser.inScope(fnParams, () => { + parser.scope.renames = fnRenames; + parser.scope.inTry = inTry; + if (fn.body.type === "BlockStatement") + parser.walkStatement(fn.body); + else parser.walkExpression(fn.body); + }); + } else if (fn && isBoundFunctionExpression(fn)) { + inTry = parser.scope.inTry; + parser.inScope( + fn.callee.object.params.filter( + i => !["require", "module", "exports"].includes(i.name) + ), + () => { + parser.scope.renames = fnRenames; + parser.scope.inTry = inTry; + if (fn.callee.object.body.type === "BlockStatement") + parser.walkStatement(fn.callee.object.body); + else parser.walkExpression(fn.callee.object.body); + } + ); + if (fn.arguments) parser.walkExpressions(fn.arguments); + } else if (fn || obj) { + parser.walkExpression(fn || obj); + } - const dep = this.newDefineDependency( - expr.range, - array ? array.range : null, - fn ? fn.range : null, - obj ? obj.range : null, - namedModule ? namedModule : null - ); - dep.loc = expr.loc; - if(namedModule) { - dep.localModule = LocalModulesHelpers.addLocalModule(parser.state, namedModule); - } - parser.state.current.addDependency(dep); - return true; - }); + const dep = this.newDefineDependency( + expr.range, + array ? array.range : null, + fn ? fn.range : null, + obj ? obj.range : null, + namedModule ? namedModule : null + ); + dep.loc = expr.loc; + if (namedModule) { + dep.localModule = LocalModulesHelpers.addLocalModule( + parser.state, + namedModule + ); + } + parser.state.current.addDependency(dep); + return true; + }); } } module.exports = AMDDefineDependencyParserPlugin; diff --git a/lib/dependencies/AMDPlugin.js b/lib/dependencies/AMDPlugin.js index cf124f3f0..06b8cd730 100644 --- a/lib/dependencies/AMDPlugin.js +++ b/lib/dependencies/AMDPlugin.js @@ -31,90 +31,219 @@ class AMDPlugin { apply(compiler) { const options = this.options; const amdOptions = this.amdOptions; - compiler.hooks.compilation.tap("AMDPlugin", (compilation, { - contextModuleFactory, - normalModuleFactory - }) => { - compilation.dependencyFactories.set(AMDRequireDependency, new NullFactory()); - compilation.dependencyTemplates.set(AMDRequireDependency, new AMDRequireDependency.Template()); + compiler.hooks.compilation.tap( + "AMDPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + AMDRequireDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + AMDRequireDependency, + new AMDRequireDependency.Template() + ); - compilation.dependencyFactories.set(AMDRequireItemDependency, normalModuleFactory); - compilation.dependencyTemplates.set(AMDRequireItemDependency, new AMDRequireItemDependency.Template()); + compilation.dependencyFactories.set( + AMDRequireItemDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + AMDRequireItemDependency, + new AMDRequireItemDependency.Template() + ); - compilation.dependencyFactories.set(AMDRequireArrayDependency, new NullFactory()); - compilation.dependencyTemplates.set(AMDRequireArrayDependency, new AMDRequireArrayDependency.Template()); + compilation.dependencyFactories.set( + AMDRequireArrayDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + AMDRequireArrayDependency, + new AMDRequireArrayDependency.Template() + ); - compilation.dependencyFactories.set(AMDRequireContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(AMDRequireContextDependency, new AMDRequireContextDependency.Template()); + compilation.dependencyFactories.set( + AMDRequireContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + AMDRequireContextDependency, + new AMDRequireContextDependency.Template() + ); - compilation.dependencyFactories.set(AMDDefineDependency, new NullFactory()); - compilation.dependencyTemplates.set(AMDDefineDependency, new AMDDefineDependency.Template()); + compilation.dependencyFactories.set( + AMDDefineDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + AMDDefineDependency, + new AMDDefineDependency.Template() + ); - compilation.dependencyFactories.set(UnsupportedDependency, new NullFactory()); - compilation.dependencyTemplates.set(UnsupportedDependency, new UnsupportedDependency.Template()); + compilation.dependencyFactories.set( + UnsupportedDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + UnsupportedDependency, + new UnsupportedDependency.Template() + ); - compilation.dependencyFactories.set(LocalModuleDependency, new NullFactory()); - compilation.dependencyTemplates.set(LocalModuleDependency, new LocalModuleDependency.Template()); + compilation.dependencyFactories.set( + LocalModuleDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + LocalModuleDependency, + new LocalModuleDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.amd !== "undefined" && !parserOptions.amd) - return; + const handler = (parser, parserOptions) => { + if (typeof parserOptions.amd !== "undefined" && !parserOptions.amd) + return; - const setExpressionToModule = (outerExpr, module) => { - parser.hooks.expression.for(outerExpr).tap("AMDPlugin", (expr) => { - const dep = new AMDRequireItemDependency(module, expr.range); - dep.userRequest = outerExpr; + const setExpressionToModule = (outerExpr, module) => { + parser.hooks.expression.for(outerExpr).tap("AMDPlugin", expr => { + const dep = new AMDRequireItemDependency(module, expr.range); + dep.userRequest = outerExpr; + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + }); + }; + + new AMDRequireDependenciesBlockParserPlugin(options).apply(parser); + new AMDDefineDependencyParserPlugin(options).apply(parser); + + setExpressionToModule("require.amd", "!!webpack amd options"); + setExpressionToModule("define.amd", "!!webpack amd options"); + setExpressionToModule("define", "!!webpack amd define"); + + parser.hooks.expression + .for("__webpack_amd_options__") + .tap("AMDPlugin", () => + parser.state.current.addVariable( + "__webpack_amd_options__", + JSON.stringify(amdOptions) + ) + ); + parser.hooks.evaluateTypeof + .for("define.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToString(typeof amdOptions) + ); + parser.hooks.evaluateTypeof + .for("require.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToString(typeof amdOptions) + ); + parser.hooks.evaluateIdentifier + .for("define.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToIdentifier("define.amd", true) + ); + parser.hooks.evaluateIdentifier + .for("require.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToIdentifier("require.amd", true) + ); + parser.hooks.typeof + .for("define") + .tap( + "AMDPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for("define") + .tap("AMDPlugin", ParserHelpers.evaluateToString("function")); + parser.hooks.canRename + .for("define") + .tap("AMDPlugin", ParserHelpers.approve); + parser.hooks.rename.for("define").tap("AMDPlugin", expr => { + const dep = new AMDRequireItemDependency( + "!!webpack amd define", + expr.range + ); + dep.userRequest = "define"; dep.loc = expr.loc; parser.state.current.addDependency(dep); - return true; + return false; }); + parser.hooks.typeof + .for("require") + .tap( + "AMDPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for("require") + .tap("AMDPlugin", ParserHelpers.evaluateToString("function")); }; - new AMDRequireDependenciesBlockParserPlugin(options).apply(parser); - new AMDDefineDependencyParserPlugin(options).apply(parser); - - setExpressionToModule("require.amd", "!!webpack amd options"); - setExpressionToModule("define.amd", "!!webpack amd options"); - setExpressionToModule("define", "!!webpack amd define"); - - parser.hooks.expression.for("__webpack_amd_options__").tap("AMDPlugin", () => - parser.state.current.addVariable("__webpack_amd_options__", JSON.stringify(amdOptions))); - parser.hooks.evaluateTypeof.for("define.amd").tap("AMDPlugin", ParserHelpers.evaluateToString(typeof amdOptions)); - parser.hooks.evaluateTypeof.for("require.amd").tap("AMDPlugin", ParserHelpers.evaluateToString(typeof amdOptions)); - parser.hooks.evaluateIdentifier.for("define.amd").tap("AMDPlugin", ParserHelpers.evaluateToIdentifier("define.amd", true)); - parser.hooks.evaluateIdentifier.for("require.amd").tap("AMDPlugin", ParserHelpers.evaluateToIdentifier("require.amd", true)); - parser.hooks.typeof.for("define").tap("AMDPlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("function"))); - parser.hooks.evaluateTypeof.for("define").tap("AMDPlugin", ParserHelpers.evaluateToString("function")); - parser.hooks.canRename.for("define").tap("AMDPlugin", ParserHelpers.approve); - parser.hooks.rename.for("define").tap("AMDPlugin", (expr) => { - const dep = new AMDRequireItemDependency("!!webpack amd define", expr.range); - dep.userRequest = "define"; - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return false; - }); - parser.hooks.typeof.for("require").tap("AMDPlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("function"))); - parser.hooks.evaluateTypeof.for("require").tap("AMDPlugin", ParserHelpers.evaluateToString("function")); - }; - - normalModuleFactory.hooks.parser.for("javascript/auto").tap("AMDPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("AMDPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("AMDPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("AMDPlugin", handler); + } + ); compiler.hooks.afterResolvers.tap("AMDPlugin", () => { - compiler.resolverFactory.hooks.resolver.for("normal").tap("AMDPlugin", resolver => { - new AliasPlugin("described-resolve", { - name: "amdefine", - alias: path.join(__dirname, "..", "..", "buildin", "amd-define.js") - }, "resolve").apply(resolver); - new AliasPlugin("described-resolve", { - name: "webpack amd options", - alias: path.join(__dirname, "..", "..", "buildin", "amd-options.js") - }, "resolve").apply(resolver); - new AliasPlugin("described-resolve", { - name: "webpack amd define", - alias: path.join(__dirname, "..", "..", "buildin", "amd-define.js") - }, "resolve").apply(resolver); - }); + compiler.resolverFactory.hooks.resolver + .for("normal") + .tap("AMDPlugin", resolver => { + new AliasPlugin( + "described-resolve", + { + name: "amdefine", + alias: path.join( + __dirname, + "..", + "..", + "buildin", + "amd-define.js" + ) + }, + "resolve" + ).apply(resolver); + new AliasPlugin( + "described-resolve", + { + name: "webpack amd options", + alias: path.join( + __dirname, + "..", + "..", + "buildin", + "amd-options.js" + ) + }, + "resolve" + ).apply(resolver); + new AliasPlugin( + "described-resolve", + { + name: "webpack amd define", + alias: path.join( + __dirname, + "..", + "..", + "buildin", + "amd-define.js" + ) + }, + "resolve" + ).apply(resolver); + }); }); } } diff --git a/lib/dependencies/AMDRequireArrayDependency.js b/lib/dependencies/AMDRequireArrayDependency.js index 33e8ec12f..ddb9c293f 100644 --- a/lib/dependencies/AMDRequireArrayDependency.js +++ b/lib/dependencies/AMDRequireArrayDependency.js @@ -24,18 +24,18 @@ AMDRequireArrayDependency.Template = class AMDRequireArrayDependencyTemplate { } getContent(dep, runtime) { - const requires = dep.depsArray.map((dependency) => { + const requires = dep.depsArray.map(dependency => { return this.contentForDependency(dependency, runtime); }); return `[${requires.join(", ")}]`; } contentForDependency(dep, runtime) { - if(typeof dep === "string") { + if (typeof dep === "string") { return dep; } - if(dep.localModule) { + if (dep.localModule) { return dep.localModule.variableName(); } else { return runtime.moduleExports({ diff --git a/lib/dependencies/AMDRequireDependenciesBlock.js b/lib/dependencies/AMDRequireDependenciesBlock.js index 05b997378..1953e0a9e 100644 --- a/lib/dependencies/AMDRequireDependenciesBlock.js +++ b/lib/dependencies/AMDRequireDependenciesBlock.js @@ -7,7 +7,15 @@ const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); const AMDRequireDependency = require("./AMDRequireDependency"); module.exports = class AMDRequireDependenciesBlock extends AsyncDependenciesBlock { - constructor(expr, arrayRange, functionRange, errorCallbackRange, module, loc, request) { + constructor( + expr, + arrayRange, + functionRange, + errorCallbackRange, + module, + loc, + request + ) { super(null, module, loc, request); this.expr = expr; this.outerRange = expr.range; @@ -15,13 +23,13 @@ module.exports = class AMDRequireDependenciesBlock extends AsyncDependenciesBloc this.functionRange = functionRange; this.errorCallbackRange = errorCallbackRange; this.bindThis = true; - if(arrayRange && functionRange && errorCallbackRange) { + if (arrayRange && functionRange && errorCallbackRange) { this.range = [arrayRange[0], errorCallbackRange[1]]; - } else if(arrayRange && functionRange) { + } else if (arrayRange && functionRange) { this.range = [arrayRange[0], functionRange[1]]; - } else if(arrayRange) { + } else if (arrayRange) { this.range = arrayRange; - } else if(functionRange) { + } else if (functionRange) { this.range = functionRange; } else { this.range = expr.range; diff --git a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js index e4c98e293..673c86fac 100644 --- a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +++ b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js @@ -24,17 +24,19 @@ class AMDRequireDependenciesBlockParserPlugin { processFunctionArgument(parser, expression) { let bindThis = true; const fnData = getFunctionExpression(expression); - if(fnData) { - parser.inScope(fnData.fn.params.filter((i) => { - return !["require", "module", "exports"].includes(i.name); - }), () => { - if(fnData.fn.body.type === "BlockStatement") - parser.walkStatement(fnData.fn.body); - else - parser.walkExpression(fnData.fn.body); - }); + if (fnData) { + parser.inScope( + fnData.fn.params.filter(i => { + return !["require", "module", "exports"].includes(i.name); + }), + () => { + if (fnData.fn.body.type === "BlockStatement") + parser.walkStatement(fnData.fn.body); + else parser.walkExpression(fnData.fn.body); + } + ); parser.walkExpressions(fnData.expressions); - if(fnData.needThis === false) { + if (fnData.needThis === false) { bindThis = false; } } else { @@ -47,43 +49,51 @@ class AMDRequireDependenciesBlockParserPlugin { const options = this.options; const processArrayForRequestString = param => { - if(param.isArray()) { - const result = param.items.map(item => processItemForRequestString(item)); - if(result.every(Boolean)) - return result.join(" "); - } else if(param.isConstArray()) { + if (param.isArray()) { + const result = param.items.map(item => + processItemForRequestString(item) + ); + if (result.every(Boolean)) return result.join(" "); + } else if (param.isConstArray()) { return param.array.join(" "); } }; const processItemForRequestString = param => { - if(param.isConditional()) { - const result = param.options.map(item => processItemForRequestString(item)); - if(result.every(Boolean)) - return result.join("|"); - } else if(param.isString()) { + if (param.isConditional()) { + const result = param.options.map(item => + processItemForRequestString(item) + ); + if (result.every(Boolean)) return result.join("|"); + } else if (param.isString()) { return param.string; } }; const processArray = (expr, param) => { - if(param.isArray()) { - for(const p of param.items) { + if (param.isArray()) { + for (const p of param.items) { const result = processItem(expr, p); - if(result === undefined) { + if (result === undefined) { processContext(expr, p); } } return true; - } else if(param.isConstArray()) { + } else if (param.isConstArray()) { const deps = []; - for(const request of param.array) { + for (const request of param.array) { let dep, localModule; - if(request === "require") { + if (request === "require") { dep = "__webpack_require__"; - } else if(["exports", "module"].includes(request)) { + } else if (["exports", "module"].includes(request)) { dep = request; - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, request)) { // eslint-disable-line no-cond-assign + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + request + )) + ) { + // eslint-disable-line no-cond-assign dep = new LocalModuleDependency(localModule); dep.loc = expr.loc; parser.state.current.addDependency(dep); @@ -103,23 +113,35 @@ class AMDRequireDependenciesBlockParserPlugin { } }; const processItem = (expr, param) => { - if(param.isConditional()) { - for(const p of param.options) { + if (param.isConditional()) { + for (const p of param.options) { const result = processItem(expr, p); - if(result === undefined) { + if (result === undefined) { processContext(expr, p); } } return true; - } else if(param.isString()) { + } else if (param.isString()) { let dep, localModule; - if(param.string === "require") { + if (param.string === "require") { dep = new ConstDependency("__webpack_require__", param.string); - } else if(param.string === "module") { - dep = new ConstDependency(parser.state.module.buildInfo.moduleArgument, param.range); - } else if(param.string === "exports") { - dep = new ConstDependency(parser.state.module.buildInfo.exportsArgument, param.range); - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string)) { // eslint-disable-line no-cond-assign + } else if (param.string === "module") { + dep = new ConstDependency( + parser.state.module.buildInfo.moduleArgument, + param.range + ); + } else if (param.string === "exports") { + dep = new ConstDependency( + parser.state.module.buildInfo.exportsArgument, + param.range + ); + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string + )) + ) { + // eslint-disable-line no-cond-assign dep = new LocalModuleDependency(localModule, param.range); } else { dep = new AMDRequireItemDependency(param.string, param.range); @@ -131,70 +153,89 @@ class AMDRequireDependenciesBlockParserPlugin { } }; const processContext = (expr, param) => { - const dep = ContextDependencyHelpers.create(AMDRequireContextDependency, param.range, param, expr, options); - if(!dep) return; + const dep = ContextDependencyHelpers.create( + AMDRequireContextDependency, + param.range, + param, + expr, + options + ); + if (!dep) return; dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); return true; }; - parser.hooks.call.for("require").tap("AMDRequireDependenciesBlockParserPlugin", (expr) => { - let param; - let dep; - let result; + parser.hooks.call + .for("require") + .tap("AMDRequireDependenciesBlockParserPlugin", expr => { + let param; + let dep; + let result; - const old = parser.state.current; + const old = parser.state.current; - if(expr.arguments.length >= 1) { - param = parser.evaluateExpression(expr.arguments[0]); - dep = new AMDRequireDependenciesBlock( - expr, - param.range, - (expr.arguments.length > 1) ? expr.arguments[1].range : null, - (expr.arguments.length > 2) ? expr.arguments[2].range : null, - parser.state.module, - expr.loc, - processArrayForRequestString(param) - ); - parser.state.current = dep; - } + if (expr.arguments.length >= 1) { + param = parser.evaluateExpression(expr.arguments[0]); + dep = new AMDRequireDependenciesBlock( + expr, + param.range, + expr.arguments.length > 1 ? expr.arguments[1].range : null, + expr.arguments.length > 2 ? expr.arguments[2].range : null, + parser.state.module, + expr.loc, + processArrayForRequestString(param) + ); + parser.state.current = dep; + } - if(expr.arguments.length === 1) { - parser.inScope([], () => { - result = processArray(expr, param); - }); - parser.state.current = old; - if(!result) return; - parser.state.current.addBlock(dep); - return true; - } - - if(expr.arguments.length === 2 || expr.arguments.length === 3) { - try { + if (expr.arguments.length === 1) { parser.inScope([], () => { result = processArray(expr, param); }); - if(!result) { - dep = new UnsupportedDependency("unsupported", expr.range); - old.addDependency(dep); - if(parser.state.module) - parser.state.module.errors.push(new UnsupportedFeatureWarning(parser.state.module, "Cannot statically analyse 'require(..., ...)' in line " + expr.loc.start.line)); - dep = null; - return true; - } - dep.functionBindThis = this.processFunctionArgument(parser, expr.arguments[1]); - if(expr.arguments.length === 3) { - dep.errorCallbackBindThis = this.processFunctionArgument(parser, expr.arguments[2]); - } - } finally { parser.state.current = old; - if(dep) - parser.state.current.addBlock(dep); + if (!result) return; + parser.state.current.addBlock(dep); + return true; } - return true; - } - }); + + if (expr.arguments.length === 2 || expr.arguments.length === 3) { + try { + parser.inScope([], () => { + result = processArray(expr, param); + }); + if (!result) { + dep = new UnsupportedDependency("unsupported", expr.range); + old.addDependency(dep); + if (parser.state.module) + parser.state.module.errors.push( + new UnsupportedFeatureWarning( + parser.state.module, + "Cannot statically analyse 'require(..., ...)' in line " + + expr.loc.start.line + ) + ); + dep = null; + return true; + } + dep.functionBindThis = this.processFunctionArgument( + parser, + expr.arguments[1] + ); + if (expr.arguments.length === 3) { + dep.errorCallbackBindThis = this.processFunctionArgument( + parser, + expr.arguments[2] + ); + } + } finally { + parser.state.current = old; + if (dep) parser.state.current.addBlock(dep); + } + return true; + } + }); } } module.exports = AMDRequireDependenciesBlockParserPlugin; diff --git a/lib/dependencies/AMDRequireDependency.js b/lib/dependencies/AMDRequireDependency.js index c08f08760..fd514e25f 100644 --- a/lib/dependencies/AMDRequireDependency.js +++ b/lib/dependencies/AMDRequireDependency.js @@ -21,47 +21,113 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate { }); // has array range but no function range - if(depBlock.arrayRange && !depBlock.functionRange) { + if (depBlock.arrayRange && !depBlock.functionRange) { const startBlock = `${promise}.then(function() {`; const endBlock = `;}).catch(${runtime.onError()})`; - source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock); - source.replace(depBlock.arrayRange[1], depBlock.outerRange[1] - 1, endBlock); + source.replace( + depBlock.outerRange[0], + depBlock.arrayRange[0] - 1, + startBlock + ); + source.replace( + depBlock.arrayRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); return; } // has function range but no array range - if(depBlock.functionRange && !depBlock.arrayRange) { + if (depBlock.functionRange && !depBlock.arrayRange) { const startBlock = `${promise}.then((`; const endBlock = `).bind(exports, __webpack_require__, exports, module)).catch(${runtime.onError()})`; - source.replace(depBlock.outerRange[0], depBlock.functionRange[0] - 1, startBlock); - source.replace(depBlock.functionRange[1], depBlock.outerRange[1] - 1, endBlock); + source.replace( + depBlock.outerRange[0], + depBlock.functionRange[0] - 1, + startBlock + ); + source.replace( + depBlock.functionRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); return; } // has array range, function range, and errorCallbackRange - if(depBlock.arrayRange && depBlock.functionRange && depBlock.errorCallbackRange) { + if ( + depBlock.arrayRange && + depBlock.functionRange && + depBlock.errorCallbackRange + ) { const startBlock = `${promise}.then(function() { `; - const errorRangeBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}).catch(`; - const endBlock = `${depBlock.errorCallbackBindThis ? ".bind(this)" : ""})`; + const errorRangeBlock = `}${ + depBlock.functionBindThis ? ".bind(this)" : "" + }).catch(`; + const endBlock = `${ + depBlock.errorCallbackBindThis ? ".bind(this)" : "" + })`; - source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock); - source.insert(depBlock.arrayRange[0] + 0.9, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = "); - source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; ("); - source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);"); - source.replace(depBlock.functionRange[1], depBlock.errorCallbackRange[0] - 1, errorRangeBlock); - source.replace(depBlock.errorCallbackRange[1], depBlock.outerRange[1] - 1, endBlock); + source.replace( + depBlock.outerRange[0], + depBlock.arrayRange[0] - 1, + startBlock + ); + source.insert( + depBlock.arrayRange[0] + 0.9, + "var __WEBPACK_AMD_REQUIRE_ARRAY__ = " + ); + source.replace( + depBlock.arrayRange[1], + depBlock.functionRange[0] - 1, + "; (" + ); + source.insert( + depBlock.functionRange[1], + ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);" + ); + source.replace( + depBlock.functionRange[1], + depBlock.errorCallbackRange[0] - 1, + errorRangeBlock + ); + source.replace( + depBlock.errorCallbackRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); return; } // has array range, function range, but no errorCallbackRange - if(depBlock.arrayRange && depBlock.functionRange) { + if (depBlock.arrayRange && depBlock.functionRange) { const startBlock = `${promise}.then(function() { `; - const endBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}).catch(${runtime.onError()})`; - source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock); - source.insert(depBlock.arrayRange[0] + 0.9, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = "); - source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; ("); - source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);"); - source.replace(depBlock.functionRange[1], depBlock.outerRange[1] - 1, endBlock); + const endBlock = `}${ + depBlock.functionBindThis ? ".bind(this)" : "" + }).catch(${runtime.onError()})`; + source.replace( + depBlock.outerRange[0], + depBlock.arrayRange[0] - 1, + startBlock + ); + source.insert( + depBlock.arrayRange[0] + 0.9, + "var __WEBPACK_AMD_REQUIRE_ARRAY__ = " + ); + source.replace( + depBlock.arrayRange[1], + depBlock.functionRange[0] - 1, + "; (" + ); + source.insert( + depBlock.functionRange[1], + ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);" + ); + source.replace( + depBlock.functionRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); } } }; diff --git a/lib/dependencies/CommonJsPlugin.js b/lib/dependencies/CommonJsPlugin.js index e2f39c441..fc6cae7ec 100644 --- a/lib/dependencies/CommonJsPlugin.js +++ b/lib/dependencies/CommonJsPlugin.js @@ -25,66 +25,137 @@ class CommonJsPlugin { apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("CommonJsPlugin", (compilation, { - contextModuleFactory, - normalModuleFactory - }) => { - compilation.dependencyFactories.set(CommonJsRequireDependency, normalModuleFactory); - compilation.dependencyTemplates.set(CommonJsRequireDependency, new CommonJsRequireDependency.Template()); + compiler.hooks.compilation.tap( + "CommonJsPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + CommonJsRequireDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + CommonJsRequireDependency, + new CommonJsRequireDependency.Template() + ); - compilation.dependencyFactories.set(CommonJsRequireContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(CommonJsRequireContextDependency, new CommonJsRequireContextDependency.Template()); + compilation.dependencyFactories.set( + CommonJsRequireContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + CommonJsRequireContextDependency, + new CommonJsRequireContextDependency.Template() + ); - compilation.dependencyFactories.set(RequireResolveDependency, normalModuleFactory); - compilation.dependencyTemplates.set(RequireResolveDependency, new RequireResolveDependency.Template()); + compilation.dependencyFactories.set( + RequireResolveDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + RequireResolveDependency, + new RequireResolveDependency.Template() + ); - compilation.dependencyFactories.set(RequireResolveContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(RequireResolveContextDependency, new RequireResolveContextDependency.Template()); + compilation.dependencyFactories.set( + RequireResolveContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + RequireResolveContextDependency, + new RequireResolveContextDependency.Template() + ); - compilation.dependencyFactories.set(RequireResolveHeaderDependency, new NullFactory()); - compilation.dependencyTemplates.set(RequireResolveHeaderDependency, new RequireResolveHeaderDependency.Template()); + compilation.dependencyFactories.set( + RequireResolveHeaderDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + RequireResolveHeaderDependency, + new RequireResolveHeaderDependency.Template() + ); - compilation.dependencyFactories.set(RequireHeaderDependency, new NullFactory()); - compilation.dependencyTemplates.set(RequireHeaderDependency, new RequireHeaderDependency.Template()); + compilation.dependencyFactories.set( + RequireHeaderDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + RequireHeaderDependency, + new RequireHeaderDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.commonjs !== "undefined" && !parserOptions.commonjs) - return; + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.commonjs !== "undefined" && + !parserOptions.commonjs + ) + return; - const requireExpressions = ["require", "require.resolve", "require.resolveWeak"]; - for(let expression of requireExpressions) { - parser.hooks.typeof.for(expression).tap("CommonJsPlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("function"))); - parser.hooks.evaluateTypeof.for(expression).tap("CommonJsPlugin", ParserHelpers.evaluateToString("function")); - parser.hooks.evaluateIdentifier.for(expression).tap("CommonJsPlugin", ParserHelpers.evaluateToIdentifier(expression, true)); - } + const requireExpressions = [ + "require", + "require.resolve", + "require.resolveWeak" + ]; + for (let expression of requireExpressions) { + parser.hooks.typeof + .for(expression) + .tap( + "CommonJsPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for(expression) + .tap( + "CommonJsPlugin", + ParserHelpers.evaluateToString("function") + ); + parser.hooks.evaluateIdentifier + .for(expression) + .tap( + "CommonJsPlugin", + ParserHelpers.evaluateToIdentifier(expression, true) + ); + } - parser.hooks.evaluateTypeof.for("module").tap("CommonJsPlugin", ParserHelpers.evaluateToString("object")); - parser.hooks.assign.for("require").tap("CommonJsPlugin", (expr) => { - // to not leak to global "require", we need to define a local require here. - const dep = new ConstDependency("var require;", 0); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - parser.scope.definitions.add("require"); - return true; - }); - parser.hooks.canRename.for("require").tap("CommonJsPlugin", () => true); - parser.hooks.rename.for("require").tap("CommonJsPlugin", (expr) => { - // define the require variable. It's still undefined, but not "not defined". - const dep = new ConstDependency("var require;", 0); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return false; - }); - parser.hooks.typeof.for("module").tap("CommonJsPlugin", () => true); - parser.hooks.evaluateTypeof.for("exports").tap("CommonJsPlugin", ParserHelpers.evaluateToString("object")); + parser.hooks.evaluateTypeof + .for("module") + .tap("CommonJsPlugin", ParserHelpers.evaluateToString("object")); + parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => { + // to not leak to global "require", we need to define a local require here. + const dep = new ConstDependency("var require;", 0); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + parser.scope.definitions.add("require"); + return true; + }); + parser.hooks.canRename + .for("require") + .tap("CommonJsPlugin", () => true); + parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => { + // define the require variable. It's still undefined, but not "not defined". + const dep = new ConstDependency("var require;", 0); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return false; + }); + parser.hooks.typeof.for("module").tap("CommonJsPlugin", () => true); + parser.hooks.evaluateTypeof + .for("exports") + .tap("CommonJsPlugin", ParserHelpers.evaluateToString("object")); - new CommonJsRequireDependencyParserPlugin(options).apply(parser); - new RequireResolveDependencyParserPlugin(options).apply(parser); - }; + new CommonJsRequireDependencyParserPlugin(options).apply(parser); + new RequireResolveDependencyParserPlugin(options).apply(parser); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("CommonJsPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("CommonJsPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("CommonJsPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("CommonJsPlugin", handler); + } + ); } } module.exports = CommonJsPlugin; diff --git a/lib/dependencies/CommonJsRequireContextDependency.js b/lib/dependencies/CommonJsRequireContextDependency.js index 6e9ed1dc0..723a849e7 100644 --- a/lib/dependencies/CommonJsRequireContextDependency.js +++ b/lib/dependencies/CommonJsRequireContextDependency.js @@ -16,7 +16,6 @@ class CommonJsRequireContextDependency extends ContextDependency { get type() { return "cjs require context"; } - } CommonJsRequireContextDependency.Template = ContextDependencyTemplateAsRequireCall; diff --git a/lib/dependencies/CommonJsRequireDependencyParserPlugin.js b/lib/dependencies/CommonJsRequireDependencyParserPlugin.js index e594077aa..14b8b7848 100644 --- a/lib/dependencies/CommonJsRequireDependencyParserPlugin.js +++ b/lib/dependencies/CommonJsRequireDependencyParserPlugin.js @@ -21,7 +21,7 @@ class CommonJsRequireDependencyParserPlugin { const options = this.options; const processItem = (expr, param) => { - if(param.isString()) { + if (param.isString()) { const dep = new CommonJsRequireDependency(param.string, param.range); dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; @@ -30,67 +30,96 @@ class CommonJsRequireDependencyParserPlugin { } }; const processContext = (expr, param) => { - const dep = ContextDependencyHelpers.create(CommonJsRequireContextDependency, expr.range, param, expr, options); - if(!dep) return; + const dep = ContextDependencyHelpers.create( + CommonJsRequireContextDependency, + expr.range, + param, + expr, + options + ); + if (!dep) return; dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); return true; }; - parser.hooks.expression.for("require.cache").tap("CommonJsRequireDependencyParserPlugin", ParserHelpers.toConstantDependencyWithWebpackRequire(parser, "__webpack_require__.c")); - parser.hooks.expression.for("require").tap("CommonJsRequireDependencyParserPlugin", (expr) => { - const dep = new CommonJsRequireContextDependency({ - request: options.unknownContextRequest, - recursive: options.unknownContextRecursive, - regExp: options.unknownContextRegExp, - mode: "sync" - }, expr.range); - dep.critical = options.unknownContextCritical && "require function is used in a way in which dependencies cannot be statically extracted"; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - }); - parser.hooks.call.for("require").tap("CommonJsRequireDependencyParserPlugin", (expr) => { - if(expr.arguments.length !== 1) return; - let localModule; - const param = parser.evaluateExpression(expr.arguments[0]); - if(param.isConditional()) { - let isExpression = false; - const prevLength = parser.state.current.dependencies.length; - const dep = new RequireHeaderDependency(expr.callee.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - for(const p of param.options) { - const result = processItem(expr, p); - if(result === undefined) { - isExpression = true; - } - } - if(isExpression) { - parser.state.current.dependencies.length = prevLength; - } else { - return true; - } - } - if(param.isString() && (localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string))) { - const dep = new LocalModuleDependency(localModule, expr.range); + parser.hooks.expression + .for("require.cache") + .tap( + "CommonJsRequireDependencyParserPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.c" + ) + ); + parser.hooks.expression + .for("require") + .tap("CommonJsRequireDependencyParserPlugin", expr => { + const dep = new CommonJsRequireContextDependency( + { + request: options.unknownContextRequest, + recursive: options.unknownContextRecursive, + regExp: options.unknownContextRegExp, + mode: "sync" + }, + expr.range + ); + dep.critical = + options.unknownContextCritical && + "require function is used in a way in which dependencies cannot be statically extracted"; dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); return true; - } else { - const result = processItem(expr, param); - if(result === undefined) { - processContext(expr, param); - } else { + }); + parser.hooks.call + .for("require") + .tap("CommonJsRequireDependencyParserPlugin", expr => { + if (expr.arguments.length !== 1) return; + let localModule; + const param = parser.evaluateExpression(expr.arguments[0]); + if (param.isConditional()) { + let isExpression = false; + const prevLength = parser.state.current.dependencies.length; const dep = new RequireHeaderDependency(expr.callee.range); dep.loc = expr.loc; parser.state.current.addDependency(dep); + for (const p of param.options) { + const result = processItem(expr, p); + if (result === undefined) { + isExpression = true; + } + } + if (isExpression) { + parser.state.current.dependencies.length = prevLength; + } else { + return true; + } } - return true; - } - }); + if ( + param.isString() && + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string + )) + ) { + const dep = new LocalModuleDependency(localModule, expr.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + } else { + const result = processItem(expr, param); + if (result === undefined) { + processContext(expr, param); + } else { + const dep = new RequireHeaderDependency(expr.callee.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + } + return true; + } + }); } } module.exports = CommonJsRequireDependencyParserPlugin; diff --git a/lib/dependencies/ConstDependency.js b/lib/dependencies/ConstDependency.js index 1e6fbc180..22edb8e23 100644 --- a/lib/dependencies/ConstDependency.js +++ b/lib/dependencies/ConstDependency.js @@ -21,7 +21,7 @@ class ConstDependency extends NullDependency { ConstDependency.Template = class ConstDependencyTemplate { apply(dep, source) { - if(typeof dep.range === "number") { + if (typeof dep.range === "number") { source.insert(dep.range, dep.expression); return; } diff --git a/lib/dependencies/ContextDependency.js b/lib/dependencies/ContextDependency.js index 1eebd51f4..81b7a7792 100644 --- a/lib/dependencies/ContextDependency.js +++ b/lib/dependencies/ContextDependency.js @@ -6,7 +6,7 @@ const Dependency = require("../Dependency"); const CriticalDependencyWarning = require("./CriticalDependencyWarning"); -const regExpToString = r => r ? r + "" : ""; +const regExpToString = r => (r ? r + "" : ""); class ContextDependency extends Dependency { // options: { request, recursive, regExp, include, exclude, mode, chunkName } @@ -15,25 +15,33 @@ class ContextDependency extends Dependency { this.options = options; this.userRequest = this.options.request; this.hadGlobalOrStickyRegExp = false; - if(this.options.regExp.global || this.options.regExp.sticky) { + if (this.options.regExp.global || this.options.regExp.sticky) { this.options.regExp = null; this.hadGlobalOrStickyRegExp = true; } } getResourceIdentifier() { - return `context${this.options.request} ${this.options.recursive} ` + - `${regExpToString(this.options.regExp)} ${regExpToString(this.options.include)} ${regExpToString(this.options.exclude)} ` + - `${this.options.mode} ${this.options.chunkName}`; + return ( + `context${this.options.request} ${this.options.recursive} ` + + `${regExpToString(this.options.regExp)} ${regExpToString( + this.options.include + )} ${regExpToString(this.options.exclude)} ` + + `${this.options.mode} ${this.options.chunkName}` + ); } getWarnings() { let warnings = super.getWarnings() || []; - if(this.critical) { + if (this.critical) { warnings.push(new CriticalDependencyWarning(this.critical)); } - if(this.hadGlobalOrStickyRegExp) { - warnings.push(new CriticalDependencyWarning("Contexts can't use RegExps with the 'g' or 'y' flags.")); + if (this.hadGlobalOrStickyRegExp) { + warnings.push( + new CriticalDependencyWarning( + "Contexts can't use RegExps with the 'g' or 'y' flags." + ) + ); } return warnings; } @@ -42,10 +50,14 @@ class ContextDependency extends Dependency { Object.defineProperty(ContextDependency.prototype, "async", { configurable: false, get() { - throw new Error("ContextDependency.async was removed. Use ContextDependency.options.mode instead."); + throw new Error( + "ContextDependency.async was removed. Use ContextDependency.options.mode instead." + ); }, set() { - throw new Error("ContextDependency.async was removed. Pass options.mode to constructor instead"); + throw new Error( + "ContextDependency.async was removed. Pass options.mode to constructor instead" + ); } }); diff --git a/lib/dependencies/ContextDependencyHelpers.js b/lib/dependencies/ContextDependencyHelpers.js index 059f68e16..a94186c29 100644 --- a/lib/dependencies/ContextDependencyHelpers.js +++ b/lib/dependencies/ContextDependencyHelpers.js @@ -15,7 +15,14 @@ const quotemeta = str => { return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&"); }; -ContextDependencyHelpers.create = (Dep, range, param, expr, options, contextOptions) => { +ContextDependencyHelpers.create = ( + Dep, + range, + param, + expr, + options, + contextOptions +) => { let dep; let prefix; let postfix; @@ -24,63 +31,112 @@ ContextDependencyHelpers.create = (Dep, range, param, expr, options, contextOpti let idx; let context; let regExp; - if(param.isTemplateString()) { + if (param.isTemplateString()) { prefix = param.quasis[0].string; - postfix = param.quasis.length > 1 ? param.quasis[param.quasis.length - 1].string : ""; + postfix = + param.quasis.length > 1 + ? param.quasis[param.quasis.length - 1].string + : ""; prefixRange = [param.quasis[0].range[0], param.quasis[0].range[1]]; valueRange = param.range; idx = prefix.lastIndexOf("/"); context = "."; - if(idx >= 0) { + if (idx >= 0) { context = prefix.substr(0, idx); prefix = `.${prefix.substr(idx)}`; } // If there are more than two quasis, maybe the generated RegExp can be more precise? - regExp = new RegExp(`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(postfix)}$`); - dep = new Dep(Object.assign({ - request: context, - recursive: options.wrappedContextRecursive, - regExp, - mode: "sync" - }, contextOptions), range, valueRange); + regExp = new RegExp( + `^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta( + postfix + )}$` + ); + dep = new Dep( + Object.assign( + { + request: context, + recursive: options.wrappedContextRecursive, + regExp, + mode: "sync" + }, + contextOptions + ), + range, + valueRange + ); dep.loc = expr.loc; - dep.replaces = [{ - range: prefixRange, - value: prefix - }]; - dep.critical = options.wrappedContextCritical && "a part of the request of a dependency is an expression"; + dep.replaces = [ + { + range: prefixRange, + value: prefix + } + ]; + dep.critical = + options.wrappedContextCritical && + "a part of the request of a dependency is an expression"; return dep; - } else if(param.isWrapped() && (param.prefix && param.prefix.isString() || param.postfix && param.postfix.isString())) { + } else if ( + param.isWrapped() && + ((param.prefix && param.prefix.isString()) || + (param.postfix && param.postfix.isString())) + ) { prefix = param.prefix && param.prefix.isString() ? param.prefix.string : ""; - postfix = param.postfix && param.postfix.isString() ? param.postfix.string : ""; - prefixRange = param.prefix && param.prefix.isString() ? param.prefix.range : null; - valueRange = [prefixRange ? prefixRange[1] : param.range[0], param.range[1]]; + postfix = + param.postfix && param.postfix.isString() ? param.postfix.string : ""; + prefixRange = + param.prefix && param.prefix.isString() ? param.prefix.range : null; + valueRange = [ + prefixRange ? prefixRange[1] : param.range[0], + param.range[1] + ]; idx = prefix.lastIndexOf("/"); context = "."; - if(idx >= 0) { + if (idx >= 0) { context = prefix.substr(0, idx); prefix = `.${prefix.substr(idx)}`; } - regExp = new RegExp(`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(postfix)}$`); - dep = new Dep(Object.assign({ - request: context, - recursive: options.wrappedContextRecursive, - regExp, - mode: "sync" - }, contextOptions), range, valueRange); + regExp = new RegExp( + `^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta( + postfix + )}$` + ); + dep = new Dep( + Object.assign( + { + request: context, + recursive: options.wrappedContextRecursive, + regExp, + mode: "sync" + }, + contextOptions + ), + range, + valueRange + ); dep.loc = expr.loc; dep.prepend = param.prefix && param.prefix.isString() ? prefix : null; - dep.critical = options.wrappedContextCritical && "a part of the request of a dependency is an expression"; + dep.critical = + options.wrappedContextCritical && + "a part of the request of a dependency is an expression"; return dep; } else { - dep = new Dep(Object.assign({ - request: options.exprContextRequest, - recursive: options.exprContextRecursive, - regExp: options.exprContextRegExp, - mode: "sync" - }, contextOptions), range, param.range); + dep = new Dep( + Object.assign( + { + request: options.exprContextRequest, + recursive: options.exprContextRecursive, + regExp: options.exprContextRegExp, + mode: "sync" + }, + contextOptions + ), + range, + param.range + ); dep.loc = expr.loc; - dep.critical = options.exprContextCritical && "the request of a dependency is an expression"; + dep.critical = + options.exprContextCritical && + "the request of a dependency is an expression"; return dep; } }; diff --git a/lib/dependencies/ContextDependencyTemplateAsId.js b/lib/dependencies/ContextDependencyTemplateAsId.js index 01b4cc2d6..14f5aa79e 100644 --- a/lib/dependencies/ContextDependencyTemplateAsId.js +++ b/lib/dependencies/ContextDependencyTemplateAsId.js @@ -5,25 +5,34 @@ "use strict"; class ContextDependencyTemplateAsId { - apply(dep, source, runtime) { const moduleExports = runtime.moduleExports({ module: dep.module, request: dep.request }); - if(dep.module) { - if(dep.valueRange) { - if(Array.isArray(dep.replaces)) { - for(let i = 0; i < dep.replaces.length; i++) { + if (dep.module) { + if (dep.valueRange) { + if (Array.isArray(dep.replaces)) { + for (let i = 0; i < dep.replaces.length; i++) { const rep = dep.replaces[i]; source.replace(rep.range[0], rep.range[1] - 1, rep.value); } } source.replace(dep.valueRange[1], dep.range[1] - 1, ")"); - source.replace(dep.range[0], dep.valueRange[0] - 1, `${moduleExports}.resolve(${typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : ""}`); + source.replace( + dep.range[0], + dep.valueRange[0] - 1, + `${moduleExports}.resolve(${ + typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "" + }` + ); } else { - source.replace(dep.range[0], dep.range[1] - 1, `${moduleExports}.resolve`); + source.replace( + dep.range[0], + dep.range[1] - 1, + `${moduleExports}.resolve` + ); } } else { source.replace(dep.range[0], dep.range[1] - 1, moduleExports); diff --git a/lib/dependencies/ContextDependencyTemplateAsRequireCall.js b/lib/dependencies/ContextDependencyTemplateAsRequireCall.js index c26eef9fd..5dac6c782 100644 --- a/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +++ b/lib/dependencies/ContextDependencyTemplateAsRequireCall.js @@ -5,23 +5,28 @@ "use strict"; class ContextDependencyTemplateAsRequireCall { - apply(dep, source, runtime) { const moduleExports = runtime.moduleExports({ module: dep.module, request: dep.request }); - if(dep.module) { - if(dep.valueRange) { - if(Array.isArray(dep.replaces)) { - for(let i = 0; i < dep.replaces.length; i++) { + if (dep.module) { + if (dep.valueRange) { + if (Array.isArray(dep.replaces)) { + for (let i = 0; i < dep.replaces.length; i++) { const rep = dep.replaces[i]; source.replace(rep.range[0], rep.range[1] - 1, rep.value); } } source.replace(dep.valueRange[1], dep.range[1] - 1, ")"); - source.replace(dep.range[0], dep.valueRange[0] - 1, `${moduleExports}(${typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : ""}`); + source.replace( + dep.range[0], + dep.valueRange[0] - 1, + `${moduleExports}(${ + typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "" + }` + ); } else { source.replace(dep.range[0], dep.range[1] - 1, moduleExports); } diff --git a/lib/dependencies/ContextElementDependency.js b/lib/dependencies/ContextElementDependency.js index 65e615de4..258770490 100644 --- a/lib/dependencies/ContextElementDependency.js +++ b/lib/dependencies/ContextElementDependency.js @@ -8,7 +8,7 @@ const ModuleDependency = require("./ModuleDependency"); class ContextElementDependency extends ModuleDependency { constructor(request, userRequest) { super(request); - if(userRequest) { + if (userRequest) { this.userRequest = userRequest; } } diff --git a/lib/dependencies/HarmonyAcceptDependency.js b/lib/dependencies/HarmonyAcceptDependency.js index 38c07e8ba..f152efb8f 100644 --- a/lib/dependencies/HarmonyAcceptDependency.js +++ b/lib/dependencies/HarmonyAcceptDependency.js @@ -23,12 +23,17 @@ class HarmonyAcceptDependency extends NullDependency { HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate { apply(dep, source, runtime) { const content = dep.dependencies - .filter(dependency => HarmonyImportDependency.Template.isImportEmitted(dependency, source)) + .filter(dependency => + HarmonyImportDependency.Template.isImportEmitted(dependency, source) + ) .map(dependency => dependency.getImportStatement(true, runtime)) .join(""); - if(dep.hasCallback) { - source.insert(dep.range[0], `function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(`); + if (dep.hasCallback) { + source.insert( + dep.range[0], + `function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(` + ); source.insert(dep.range[1], ")(__WEBPACK_OUTDATED_DEPENDENCIES__); }"); return; } diff --git a/lib/dependencies/HarmonyCompatibilityDependency.js b/lib/dependencies/HarmonyCompatibilityDependency.js index 29311b6fa..d6febb5ac 100644 --- a/lib/dependencies/HarmonyCompatibilityDependency.js +++ b/lib/dependencies/HarmonyCompatibilityDependency.js @@ -19,7 +19,7 @@ class HarmonyCompatibilityDependency extends NullDependency { HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate { apply(dep, source, runtime) { const usedExports = dep.originModule.usedExports; - if(usedExports !== false && !Array.isArray(usedExports)) { + if (usedExports !== false && !Array.isArray(usedExports)) { const content = runtime.defineEsModuleFlagStatement({ exportsArgument: dep.originModule.exportsArgument }); diff --git a/lib/dependencies/HarmonyDetectionParserPlugin.js b/lib/dependencies/HarmonyDetectionParserPlugin.js index 05f260879..4599c2e3d 100644 --- a/lib/dependencies/HarmonyDetectionParserPlugin.js +++ b/lib/dependencies/HarmonyDetectionParserPlugin.js @@ -9,12 +9,14 @@ const HarmonyInitDependency = require("./HarmonyInitDependency"); module.exports = class HarmonyDetectionParserPlugin { apply(parser) { - parser.hooks.program.tap("HarmonyDetectionParserPlugin", (ast) => { + parser.hooks.program.tap("HarmonyDetectionParserPlugin", ast => { const isStrictHarmony = parser.state.module.type === "javascript/esm"; - const isHarmony = isStrictHarmony || ast.body.some(statement => { - return /^(Import|Export).*Declaration$/.test(statement.type); - }); - if(isHarmony) { + const isHarmony = + isStrictHarmony || + ast.body.some(statement => { + return /^(Import|Export).*Declaration$/.test(statement.type); + }); + if (isHarmony) { const module = parser.state.module; const compatDep = new HarmonyCompatibilityDependency(module); compatDep.loc = { @@ -47,7 +49,7 @@ module.exports = class HarmonyDetectionParserPlugin { module.buildMeta.exportsType = "namespace"; module.buildInfo.strict = true; module.buildInfo.exportsArgument = "__webpack_exports__"; - if(isStrictHarmony) { + if (isStrictHarmony) { module.buildMeta.strictHarmonyModule = true; module.buildInfo.moduleArgument = "__webpack_module__"; } @@ -56,23 +58,33 @@ module.exports = class HarmonyDetectionParserPlugin { const skipInHarmony = () => { const module = parser.state.module; - if(module && module.buildMeta && module.buildMeta.exportsType) + if (module && module.buildMeta && module.buildMeta.exportsType) return true; }; const nullInHarmony = () => { const module = parser.state.module; - if(module && module.buildMeta && module.buildMeta.exportsType) + if (module && module.buildMeta && module.buildMeta.exportsType) return null; }; const nonHarmonyIdentifiers = ["define", "exports"]; - for(const identifer of nonHarmonyIdentifiers) { - parser.hooks.evaluateTypeof.for(identifer).tap("HarmonyDetectionParserPlugin", nullInHarmony); - parser.hooks.typeof.for(identifer).tap("HarmonyDetectionParserPlugin", skipInHarmony); - parser.hooks.evaluate.for(identifer).tap("HarmonyDetectionParserPlugin", nullInHarmony); - parser.hooks.expression.for(identifer).tap("HarmonyDetectionParserPlugin", skipInHarmony); - parser.hooks.call.for(identifer).tap("HarmonyDetectionParserPlugin", skipInHarmony); + for (const identifer of nonHarmonyIdentifiers) { + parser.hooks.evaluateTypeof + .for(identifer) + .tap("HarmonyDetectionParserPlugin", nullInHarmony); + parser.hooks.typeof + .for(identifer) + .tap("HarmonyDetectionParserPlugin", skipInHarmony); + parser.hooks.evaluate + .for(identifer) + .tap("HarmonyDetectionParserPlugin", nullInHarmony); + parser.hooks.expression + .for(identifer) + .tap("HarmonyDetectionParserPlugin", skipInHarmony); + parser.hooks.call + .for(identifer) + .tap("HarmonyDetectionParserPlugin", skipInHarmony); } } }; diff --git a/lib/dependencies/HarmonyExportDependencyParserPlugin.js b/lib/dependencies/HarmonyExportDependencyParserPlugin.js index 168483251..de2d9c257 100644 --- a/lib/dependencies/HarmonyExportDependencyParserPlugin.js +++ b/lib/dependencies/HarmonyExportDependencyParserPlugin.js @@ -17,65 +17,123 @@ module.exports = class HarmonyExportDependencyParserPlugin { } apply(parser) { - parser.hooks.export.tap("HarmonyExportDependencyParserPlugin", statement => { - const dep = new HarmonyExportHeaderDependency(statement.declaration && statement.declaration.range, statement.range); - dep.loc = Object.create(statement.loc); - dep.loc.index = -1; - parser.state.current.addDependency(dep); - return true; - }); - parser.hooks.exportImport.tap("HarmonyExportDependencyParserPlugin", (statement, source) => { - parser.state.lastHarmonyImportOrder = (parser.state.lastHarmonyImportOrder || 0) + 1; - const clearDep = new ConstDependency("", statement.range); - clearDep.loc = Object.create(statement.loc); - clearDep.loc.index = -1; - parser.state.current.addDependency(clearDep); - const sideEffectDep = new HarmonyImportSideEffectDependency(source, parser.state.module, parser.state.lastHarmonyImportOrder, parser.state.harmonyParserScope); - sideEffectDep.loc = Object.create(statement.loc); - sideEffectDep.loc.index = -1; - parser.state.current.addDependency(sideEffectDep); - return true; - }); - parser.hooks.exportExpression.tap("HarmonyExportDependencyParserPlugin", (statement, expr) => { - const dep = new HarmonyExportExpressionDependency(parser.state.module, expr.range, statement.range); - dep.loc = Object.create(statement.loc); - dep.loc.index = -1; - parser.state.current.addDependency(dep); - return true; - }); - parser.hooks.exportDeclaration.tap("HarmonyExportDependencyParserPlugin", statement => {}); - parser.hooks.exportSpecifier.tap("HarmonyExportDependencyParserPlugin", (statement, id, name, idx) => { - const rename = parser.scope.renames.get(id); - let dep; - const harmonyNamedExports = parser.state.harmonyNamedExports = parser.state.harmonyNamedExports || new Set(); - harmonyNamedExports.add(name); - if(rename === "imported var") { - const settings = parser.state.harmonySpecifier.get(id); - dep = new HarmonyExportImportedSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, settings.id, name, harmonyNamedExports, null, this.strictExportPresence); - } else { - dep = new HarmonyExportSpecifierDependency(parser.state.module, id, name); + parser.hooks.export.tap( + "HarmonyExportDependencyParserPlugin", + statement => { + const dep = new HarmonyExportHeaderDependency( + statement.declaration && statement.declaration.range, + statement.range + ); + dep.loc = Object.create(statement.loc); + dep.loc.index = -1; + parser.state.current.addDependency(dep); + return true; } - dep.loc = Object.create(statement.loc); - dep.loc.index = idx; - parser.state.current.addDependency(dep); - return true; - }); - parser.hooks.exportImportSpecifier.tap("HarmonyExportDependencyParserPlugin", (statement, source, id, name, idx) => { - const harmonyNamedExports = parser.state.harmonyNamedExports = parser.state.harmonyNamedExports || new Set(); - let harmonyStarExports = null; - if(name) { + ); + parser.hooks.exportImport.tap( + "HarmonyExportDependencyParserPlugin", + (statement, source) => { + parser.state.lastHarmonyImportOrder = + (parser.state.lastHarmonyImportOrder || 0) + 1; + const clearDep = new ConstDependency("", statement.range); + clearDep.loc = Object.create(statement.loc); + clearDep.loc.index = -1; + parser.state.current.addDependency(clearDep); + const sideEffectDep = new HarmonyImportSideEffectDependency( + source, + parser.state.module, + parser.state.lastHarmonyImportOrder, + parser.state.harmonyParserScope + ); + sideEffectDep.loc = Object.create(statement.loc); + sideEffectDep.loc.index = -1; + parser.state.current.addDependency(sideEffectDep); + return true; + } + ); + parser.hooks.exportExpression.tap( + "HarmonyExportDependencyParserPlugin", + (statement, expr) => { + const dep = new HarmonyExportExpressionDependency( + parser.state.module, + expr.range, + statement.range + ); + dep.loc = Object.create(statement.loc); + dep.loc.index = -1; + parser.state.current.addDependency(dep); + return true; + } + ); + parser.hooks.exportDeclaration.tap( + "HarmonyExportDependencyParserPlugin", + statement => {} + ); + parser.hooks.exportSpecifier.tap( + "HarmonyExportDependencyParserPlugin", + (statement, id, name, idx) => { + const rename = parser.scope.renames.get(id); + let dep; + const harmonyNamedExports = (parser.state.harmonyNamedExports = + parser.state.harmonyNamedExports || new Set()); harmonyNamedExports.add(name); - } else { - harmonyStarExports = parser.state.harmonyStarExports = parser.state.harmonyStarExports || []; + if (rename === "imported var") { + const settings = parser.state.harmonySpecifier.get(id); + dep = new HarmonyExportImportedSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + settings.id, + name, + harmonyNamedExports, + null, + this.strictExportPresence + ); + } else { + dep = new HarmonyExportSpecifierDependency( + parser.state.module, + id, + name + ); + } + dep.loc = Object.create(statement.loc); + dep.loc.index = idx; + parser.state.current.addDependency(dep); + return true; } - const dep = new HarmonyExportImportedSpecifierDependency(source, parser.state.module, parser.state.lastHarmonyImportOrder, parser.state.harmonyParserScope, id, name, harmonyNamedExports, harmonyStarExports && harmonyStarExports.slice(), this.strictExportPresence); - if(harmonyStarExports) { - harmonyStarExports.push(dep); + ); + parser.hooks.exportImportSpecifier.tap( + "HarmonyExportDependencyParserPlugin", + (statement, source, id, name, idx) => { + const harmonyNamedExports = (parser.state.harmonyNamedExports = + parser.state.harmonyNamedExports || new Set()); + let harmonyStarExports = null; + if (name) { + harmonyNamedExports.add(name); + } else { + harmonyStarExports = parser.state.harmonyStarExports = + parser.state.harmonyStarExports || []; + } + const dep = new HarmonyExportImportedSpecifierDependency( + source, + parser.state.module, + parser.state.lastHarmonyImportOrder, + parser.state.harmonyParserScope, + id, + name, + harmonyNamedExports, + harmonyStarExports && harmonyStarExports.slice(), + this.strictExportPresence + ); + if (harmonyStarExports) { + harmonyStarExports.push(dep); + } + dep.loc = Object.create(statement.loc); + dep.loc.index = idx; + parser.state.current.addDependency(dep); + return true; } - dep.loc = Object.create(statement.loc); - dep.loc.index = idx; - parser.state.current.addDependency(dep); - return true; - }); + ); } }; diff --git a/lib/dependencies/HarmonyExportExpressionDependency.js b/lib/dependencies/HarmonyExportExpressionDependency.js index 610ac7a20..56344e43f 100644 --- a/lib/dependencies/HarmonyExportExpressionDependency.js +++ b/lib/dependencies/HarmonyExportExpressionDependency.js @@ -29,7 +29,7 @@ HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTempla const used = dep.originModule.isUsed("default"); const content = this.getContent(dep.originModule, used); - if(dep.range) { + if (dep.range) { source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "("); source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); return; @@ -40,8 +40,10 @@ HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTempla getContent(module, used) { const exportsName = module.exportsArgument; - if(used) { - return `/* harmony default export */ ${exportsName}[${JSON.stringify(used)}] = `; + if (used) { + return `/* harmony default export */ ${exportsName}[${JSON.stringify( + used + )}] = `; } return "/* unused harmony default export */ var _unused_webpack_default_export = "; } diff --git a/lib/dependencies/HarmonyExportHeaderDependency.js b/lib/dependencies/HarmonyExportHeaderDependency.js index bf06a5980..a0e9918bd 100644 --- a/lib/dependencies/HarmonyExportHeaderDependency.js +++ b/lib/dependencies/HarmonyExportHeaderDependency.js @@ -20,7 +20,9 @@ class HarmonyExportHeaderDependency extends NullDependency { HarmonyExportHeaderDependency.Template = class HarmonyExportDependencyTemplate { apply(dep, source) { const content = ""; - const replaceUntil = dep.range ? dep.range[0] - 1 : dep.rangeStatement[1] - 1; + const replaceUntil = dep.range + ? dep.range[0] - 1 + : dep.rangeStatement[1] - 1; source.replace(dep.rangeStatement[0], replaceUntil, content); } }; diff --git a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js index fab8eb876..b0eefc1fd 100644 --- a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +++ b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js @@ -7,7 +7,17 @@ const HarmonyImportDependency = require("./HarmonyImportDependency"); const Template = require("../Template"); class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { - constructor(request, originModule, sourceOrder, parserScope, id, name, activeExports, otherStarExports, strictExportPresence) { + constructor( + request, + originModule, + sourceOrder, + parserScope, + id, + name, + activeExports, + otherStarExports, + strictExportPresence + ) { super(request, originModule, sourceOrder, parserScope); this.id = id; this.name = name; @@ -26,24 +36,28 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { const used = this.originModule.isUsed(name); const importedModule = this.module; - if(!importedModule) { + if (!importedModule) { return { type: "missing", userRequest: this.userRequest }; } - if(!ignoreUnused && (name ? !used : this.originModule.usedExports === false)) { + if ( + !ignoreUnused && + (name ? !used : this.originModule.usedExports === false) + ) { return { type: "unused", name: name || "*" }; } - const isNotAHarmonyModule = importedModule.buildMeta && !importedModule.buildMeta.exportsType; + const isNotAHarmonyModule = + importedModule.buildMeta && !importedModule.buildMeta.exportsType; const strictHarmonyModule = this.originModule.buildMeta.strictHarmonyModule; - if(name && id === "default" && isNotAHarmonyModule) { - if(strictHarmonyModule) { + if (name && id === "default" && isNotAHarmonyModule) { + if (strictHarmonyModule) { return { type: "reexport-non-harmony-default-strict", module: importedModule, @@ -58,10 +72,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { } } - if(name) { + if (name) { // export { name as name } - if(id) { - if(isNotAHarmonyModule && strictHarmonyModule) { + if (id) { + if (isNotAHarmonyModule && strictHarmonyModule) { return { type: "rexport-non-harmony-undefined", module: importedModule, @@ -71,15 +85,13 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { return { type: "safe-reexport", module: importedModule, - map: new Map([ - [name, id] - ]) + map: new Map([[name, id]]) }; } } // export { * as name } - if(isNotAHarmonyModule && strictHarmonyModule) { + if (isNotAHarmonyModule && strictHarmonyModule) { return { type: "reexport-fake-namespace-object", module: importedModule, @@ -95,22 +107,29 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { } const hasUsedExports = Array.isArray(this.originModule.usedExports); - const hasProvidedExports = Array.isArray(importedModule.buildMeta.providedExports); + const hasProvidedExports = Array.isArray( + importedModule.buildMeta.providedExports + ); const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports(); // export * - if(hasUsedExports) { + if (hasUsedExports) { // reexport * with known used exports - if(hasProvidedExports) { - const map = new Map(this.originModule.usedExports.filter((id) => { - if(id === "default") return false; - if(this.activeExports.has(id)) return false; - if(activeFromOtherStarExports.has(id)) return false; - if(!importedModule.buildMeta.providedExports.includes(id)) return false; - return true; - }).map(item => [item, item])); + if (hasProvidedExports) { + const map = new Map( + this.originModule.usedExports + .filter(id => { + if (id === "default") return false; + if (this.activeExports.has(id)) return false; + if (activeFromOtherStarExports.has(id)) return false; + if (!importedModule.buildMeta.providedExports.includes(id)) + return false; + return true; + }) + .map(item => [item, item]) + ); - if(map.size === 0) { + if (map.size === 0) { return { type: "empty-star" }; @@ -123,15 +142,19 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { }; } - const map = new Map(this.originModule.usedExports.filter(id => { - if(id === "default") return false; - if(this.activeExports.has(id)) return false; - if(activeFromOtherStarExports.has(id)) return false; + const map = new Map( + this.originModule.usedExports + .filter(id => { + if (id === "default") return false; + if (this.activeExports.has(id)) return false; + if (activeFromOtherStarExports.has(id)) return false; - return true; - }).map(item => [item, item])); + return true; + }) + .map(item => [item, item]) + ); - if(map.size === 0) { + if (map.size === 0) { return { type: "empty-star" }; @@ -144,19 +167,20 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { }; } - if(hasProvidedExports) { - const map = new Map(importedModule.buildMeta.providedExports - .filter(id => { - if(id === "default") return false; - if(this.activeExports.has(id)) return false; - if(activeFromOtherStarExports.has(id)) return false; + if (hasProvidedExports) { + const map = new Map( + importedModule.buildMeta.providedExports + .filter(id => { + if (id === "default") return false; + if (this.activeExports.has(id)) return false; + if (activeFromOtherStarExports.has(id)) return false; - return true; - }) - .map(item => [item, item]) + return true; + }) + .map(item => [item, item]) ); - if(map.size === 0) { + if (map.size === 0) { return { type: "empty-star" }; @@ -178,7 +202,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { getReference() { const mode = this.getMode(); - switch(mode.type) { + switch (mode.type) { case "missing": case "unused": case "empty-star": @@ -218,14 +242,16 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { } _discoverActiveExportsFromOtherStartExports() { - if(!this.otherStarExports) - return new Set(); + if (!this.otherStarExports) return new Set(); const result = new Set(); // try to learn impossible exports from other star exports with provided exports - for(const otherStarExport of this.otherStarExports) { + for (const otherStarExport of this.otherStarExports) { const otherImportedModule = otherStarExport.module; - if(otherImportedModule && Array.isArray(otherImportedModule.buildMeta.providedExports)) { - for(const exportName of otherImportedModule.buildMeta.providedExports) + if ( + otherImportedModule && + Array.isArray(otherImportedModule.buildMeta.providedExports) + ) { + for (const exportName of otherImportedModule.buildMeta.providedExports) result.add(exportName); } } @@ -233,7 +259,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { } getExports() { - if(this.name) { + if (this.name) { return { exports: [this.name] }; @@ -241,21 +267,23 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { const importedModule = this.module; - if(!importedModule) { + if (!importedModule) { // no imported module available return { exports: null }; } - if(Array.isArray(importedModule.buildMeta.providedExports)) { + if (Array.isArray(importedModule.buildMeta.providedExports)) { return { - exports: importedModule.buildMeta.providedExports.filter(id => id !== "default"), + exports: importedModule.buildMeta.providedExports.filter( + id => id !== "default" + ), dependencies: [importedModule] }; } - if(importedModule.buildMeta.providedExports) { + if (importedModule.buildMeta.providedExports) { return { exports: true }; @@ -268,14 +296,20 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { } getWarnings() { - if(this.strictExportPresence || this.originModule.buildMeta.strictHarmonyModule) { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { return []; } return this._getErrors(); } getErrors() { - if(this.strictExportPresence || this.originModule.buildMeta.strictHarmonyModule) { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { return this._getErrors(); } return []; @@ -283,34 +317,46 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { _getErrors() { const importedModule = this.module; - if(!importedModule) { + if (!importedModule) { return; } - if(!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { + if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { // It's not an harmony module - if(this.originModule.buildMeta.strictHarmonyModule && this.id !== "default") { + if ( + this.originModule.buildMeta.strictHarmonyModule && + this.id !== "default" + ) { // In strict harmony modules we only support the default export - const exportName = this.id ? `the named export '${this.id}'` : "the namespace object"; - const err = new Error(`Can't reexport ${exportName} from non EcmaScript module (only default export is available)`); + const exportName = this.id + ? `the named export '${this.id}'` + : "the namespace object"; + const err = new Error( + `Can't reexport ${ + exportName + } from non EcmaScript module (only default export is available)` + ); err.hideStack = true; return [err]; } return; } - if(!this.id) { + if (!this.id) { return; } - if(importedModule.isProvided(this.id) !== false) { + if (importedModule.isProvided(this.id) !== false) { // It's provided or we are not sure return; } // We are sure that it's not provided - const idIsNotNameMessage = this.id !== this.name ? ` (reexported as '${this.name}')` : ""; - const errorMessage = `"export '${this.id}'${idIsNotNameMessage} was not found in '${this.userRequest}'`; + const idIsNotNameMessage = + this.id !== this.name ? ` (reexported as '${this.name}')` : ""; + const errorMessage = `"export '${this.id}'${ + idIsNotNameMessage + } was not found in '${this.userRequest}'`; const err = new Error(errorMessage); err.hideStack = true; return [err]; @@ -323,13 +369,17 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { } getHashValue(importedModule) { - if(!importedModule) { + if (!importedModule) { return ""; } const stringifiedUsedExport = JSON.stringify(importedModule.usedExports); - const stringifiedProvidedExport = JSON.stringify(importedModule.buildMeta.providedExports); - return importedModule.used + stringifiedUsedExport + stringifiedProvidedExport; + const stringifiedProvidedExport = JSON.stringify( + importedModule.buildMeta.providedExports + ); + return ( + importedModule.used + stringifiedUsedExport + stringifiedProvidedExport + ); } } @@ -343,36 +393,39 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS } getHarmonyInitOrder(dep) { - if(dep.name) { + if (dep.name) { const used = dep.originModule.isUsed(dep.name); - if(!used) return NaN; + if (!used) return NaN; } else { const importedModule = dep.module; const activeFromOtherStarExports = dep._discoverActiveExportsFromOtherStartExports(); - if(Array.isArray(dep.originModule.usedExports)) { + if (Array.isArray(dep.originModule.usedExports)) { // we know which exports are used const unused = dep.originModule.usedExports.every(id => { - if(id === "default") return true; - if(dep.activeExports.has(id)) return true; - if(importedModule.isProvided(id) === false) return true; - if(activeFromOtherStarExports.has(id)) return true; + if (id === "default") return true; + if (dep.activeExports.has(id)) return true; + if (importedModule.isProvided(id) === false) return true; + if (activeFromOtherStarExports.has(id)) return true; return false; }); - if(unused) return NaN; - - } else if(dep.originModule.usedExports && importedModule && Array.isArray(importedModule.buildMeta.providedExports)) { + if (unused) return NaN; + } else if ( + dep.originModule.usedExports && + importedModule && + Array.isArray(importedModule.buildMeta.providedExports) + ) { // not sure which exports are used, but we know which are provided const unused = importedModule.buildMeta.providedExports.every(id => { - if(id === "default") return true; - if(dep.activeExports.has(id)) return true; - if(activeFromOtherStarExports.has(id)) return true; + if (id === "default") return true; + if (dep.activeExports.has(id)) return true; + if (activeFromOtherStarExports.has(id)) return true; return false; }); - if(unused) return NaN; + if (unused) return NaN; } } return super.getHarmonyInitOrder(dep); @@ -384,55 +437,134 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS const importedModule = dep.module; const importVar = dep.getImportVar(); - switch(mode.type) { + switch (mode.type) { case "missing": - return `throw new Error(${JSON.stringify(`Cannot find module '${mode.userRequest}'`)});\n`; + return `throw new Error(${JSON.stringify( + `Cannot find module '${mode.userRequest}'` + )});\n`; case "unused": - return `${Template.toNormalComment(`unused harmony reexport ${mode.name}`)}\n`; + return `${Template.toNormalComment( + `unused harmony reexport ${mode.name}` + )}\n`; case "reexport-non-harmony-default": - return "/* harmony reexport (default from non-hamory) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, null); + return ( + "/* harmony reexport (default from non-hamory) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + null + ) + ); case "reexport-fake-namespace-object": - return "/* harmony reexport (fake namespace object from non-hamory) */ " + this.getReexportFakeNamespaceObjectStatement(module, module.isUsed(mode.name), importVar); + return ( + "/* harmony reexport (fake namespace object from non-hamory) */ " + + this.getReexportFakeNamespaceObjectStatement( + module, + module.isUsed(mode.name), + importVar + ) + ); case "rexport-non-harmony-undefined": - return "/* harmony reexport (non default export from non-hamory) */ " + this.getReexportStatement(module, module.isUsed(mode.name), "undefined", ""); + return ( + "/* harmony reexport (non default export from non-hamory) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + "undefined", + "" + ) + ); case "reexport-non-harmony-default-strict": - return "/* harmony reexport (default from non-hamory) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, ""); + return ( + "/* harmony reexport (default from non-hamory) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + "" + ) + ); case "reexport-namespace-object": - return "/* harmony reexport (module object) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, ""); + return ( + "/* harmony reexport (module object) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + "" + ) + ); case "empty-star": return "/* empty/unused harmony star reexport */"; case "safe-reexport": - return Array.from(mode.map.entries()).map(item => { - return "/* harmony reexport (safe) */ " + this.getReexportStatement(module, module.isUsed(item[0]), importVar, importedModule.isUsed(item[1])) + "\n"; - }).join(""); + return Array.from(mode.map.entries()) + .map(item => { + return ( + "/* harmony reexport (safe) */ " + + this.getReexportStatement( + module, + module.isUsed(item[0]), + importVar, + importedModule.isUsed(item[1]) + ) + + "\n" + ); + }) + .join(""); case "checked-reexport": - return Array.from(mode.map.entries()).map(item => { - return "/* harmony reexport (checked) */ " + this.getConditionalReexportStatement(module, item[0], importVar, item[1]) + "\n"; - }).join(""); + return Array.from(mode.map.entries()) + .map(item => { + return ( + "/* harmony reexport (checked) */ " + + this.getConditionalReexportStatement( + module, + item[0], + importVar, + item[1] + ) + + "\n" + ); + }) + .join(""); - case "dynamic-reexport": - { - const activeExports = new Set([...dep.activeExports, ...dep._discoverActiveExportsFromOtherStartExports()]); - let content = "/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + importVar + ") "; + case "dynamic-reexport": { + const activeExports = new Set([ + ...dep.activeExports, + ...dep._discoverActiveExportsFromOtherStartExports() + ]); + let content = + "/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + + importVar + + ") "; - // Filter out exports which are defined by other exports - // and filter out default export because it cannot be reexported with * - if(activeExports.length > 0) - content += "if(" + JSON.stringify(activeExports.concat("default")) + ".indexOf(__WEBPACK_IMPORT_KEY__) < 0) "; - else - content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') "; - const exportsName = dep.originModule.exportsArgument; - return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${importVar}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`; - } + // Filter out exports which are defined by other exports + // and filter out default export because it cannot be reexported with * + if (activeExports.length > 0) + content += + "if(" + + JSON.stringify(activeExports.concat("default")) + + ".indexOf(__WEBPACK_IMPORT_KEY__) < 0) "; + else content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') "; + const exportsName = dep.originModule.exportsArgument; + return ( + content + + `(function(key) { __webpack_require__.d(${ + exportsName + }, key, function() { return ${ + importVar + }[key]; }) }(__WEBPACK_IMPORT_KEY__));\n` + ); + } default: throw new Error(`Unknown mode ${mode.type}`); @@ -442,22 +574,30 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS getReexportStatement(module, key, name, valueKey) { const exportsName = module.exportsArgument; const returnValue = this.getReturnValue(valueKey); - return `__webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return ${name}${returnValue}; });\n`; + return `__webpack_require__.d(${exportsName}, ${JSON.stringify( + key + )}, function() { return ${name}${returnValue}; });\n`; } getReexportFakeNamespaceObjectStatement(module, key, name) { const exportsName = module.exportsArgument; - return `__webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return { "default": ${name} }; });\n`; + return `__webpack_require__.d(${exportsName}, ${JSON.stringify( + key + )}, function() { return { "default": ${name} }; });\n`; } getConditionalReexportStatement(module, key, name, valueKey) { const exportsName = module.exportsArgument; const returnValue = this.getReturnValue(valueKey); - return `if(__webpack_require__.o(${name}, ${JSON.stringify(valueKey)})) __webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return ${name}${returnValue}; });\n`; + return `if(__webpack_require__.o(${name}, ${JSON.stringify( + valueKey + )})) __webpack_require__.d(${exportsName}, ${JSON.stringify( + key + )}, function() { return ${name}${returnValue}; });\n`; } getReturnValue(valueKey) { - if(valueKey === null) { + if (valueKey === null) { return "_default.a"; } diff --git a/lib/dependencies/HarmonyExportSpecifierDependency.js b/lib/dependencies/HarmonyExportSpecifierDependency.js index f6fa34c31..7b4d05bc6 100644 --- a/lib/dependencies/HarmonyExportSpecifierDependency.js +++ b/lib/dependencies/HarmonyExportSpecifierDependency.js @@ -38,13 +38,15 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen getContent(dep) { const used = dep.originModule.isUsed(dep.name); - if(!used) { - return `/* unused harmony export ${(dep.name || "namespace")} */\n`; + if (!used) { + return `/* unused harmony export ${dep.name || "namespace"} */\n`; } const exportsName = dep.originModule.exportsArgument; - return `/* harmony export (binding) */ __webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${dep.id}; });\n`; + return `/* harmony export (binding) */ __webpack_require__.d(${ + exportsName + }, ${JSON.stringify(used)}, function() { return ${dep.id}; });\n`; } }; diff --git a/lib/dependencies/HarmonyImportDependency.js b/lib/dependencies/HarmonyImportDependency.js index 746695491..fac30389f 100644 --- a/lib/dependencies/HarmonyImportDependency.js +++ b/lib/dependencies/HarmonyImportDependency.js @@ -15,7 +15,7 @@ class HarmonyImportDependency extends ModuleDependency { } getReference() { - if(!this.module) return null; + if (!this.module) return null; return { module: this.module, @@ -26,10 +26,12 @@ class HarmonyImportDependency extends ModuleDependency { getImportVar() { let importVarMap = this.parserScope.importVarMap; - if(!importVarMap) this.parserScope.importVarMap = importVarMap = new Map(); + if (!importVarMap) this.parserScope.importVarMap = importVarMap = new Map(); let importVar = importVarMap.get(this.module); - if(importVar) return importVar; - importVar = `${Template.toIdentifier(`${this.userRequest}`)}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`; + if (importVar) return importVar; + importVar = `${Template.toIdentifier( + `${this.userRequest}` + )}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`; importVarMap.set(this.module, importVar); return importVar; } @@ -47,7 +49,11 @@ class HarmonyImportDependency extends ModuleDependency { updateHash(hash) { super.updateHash(hash); const importedModule = this.module; - hash.update((importedModule && (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + ""); + hash.update( + (importedModule && + (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + + "" + ); hash.update((importedModule && importedModule.id) + ""); } } @@ -65,20 +71,23 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate { static isImportEmitted(dep, source) { let sourceInfo = importEmittedMap.get(source); - if(!sourceInfo) return false; + if (!sourceInfo) return false; const key = dep.module || dep.request; return key && sourceInfo.emittedImports.get(key); } harmonyInit(dep, source, runtime) { let sourceInfo = importEmittedMap.get(source); - if(!sourceInfo) { - importEmittedMap.set(source, sourceInfo = { - emittedImports: new Map() - }); + if (!sourceInfo) { + importEmittedMap.set( + source, + (sourceInfo = { + emittedImports: new Map() + }) + ); } const key = dep.module || dep.request; - if(key && sourceInfo.emittedImports.get(key)) return; + if (key && sourceInfo.emittedImports.get(key)) return; sourceInfo.emittedImports.set(key, true); const content = dep.getImportStatement(false, runtime); source.insert(-1, content); diff --git a/lib/dependencies/HarmonyImportDependencyParserPlugin.js b/lib/dependencies/HarmonyImportDependencyParserPlugin.js index b9e4210a8..20e51bef3 100644 --- a/lib/dependencies/HarmonyImportDependencyParserPlugin.js +++ b/lib/dependencies/HarmonyImportDependencyParserPlugin.js @@ -18,118 +18,197 @@ module.exports = class HarmonyImportDependencyParserPlugin { } apply(parser) { - parser.hooks.import.tap("HarmonyImportDependencyParserPlugin", (statement, source) => { - parser.state.lastHarmonyImportOrder = (parser.state.lastHarmonyImportOrder || 0) + 1; - const clearDep = new ConstDependency("", statement.range); - clearDep.loc = statement.loc; - parser.state.module.addDependency(clearDep); - const sideEffectDep = new HarmonyImportSideEffectDependency(source, parser.state.module, parser.state.lastHarmonyImportOrder, parser.state.harmonyParserScope); - sideEffectDep.loc = statement.loc; - parser.state.module.addDependency(sideEffectDep); - return true; - }); - parser.hooks.importSpecifier.tap("HarmonyImportDependencyParserPlugin", (statement, source, id, name) => { - parser.scope.definitions.delete(name); - parser.scope.renames.set(name, "imported var"); - if(!parser.state.harmonySpecifier) parser.state.harmonySpecifier = new Map(); - parser.state.harmonySpecifier.set(name, { - source, - id, - sourceOrder: parser.state.lastHarmonyImportOrder - }); - return true; - }); - parser.hooks.expression.for("imported var").tap("HarmonyImportDependencyParserPlugin", (expr) => { - const name = expr.name; - const settings = parser.state.harmonySpecifier.get(name); - const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, settings.id, name, expr.range, this.strictExportPresence); - dep.shorthand = parser.scope.inShorthand; - dep.directImport = true; - dep.loc = expr.loc; - parser.state.module.addDependency(dep); - return true; - }); - parser.hooks.expressionAnyMember.for("imported var").tap("HarmonyImportDependencyParserPlugin", (expr) => { - const name = expr.object.name; - const settings = parser.state.harmonySpecifier.get(name); - if(settings.id !== null) - return false; - const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, expr.property.name || expr.property.value, name, expr.range, this.strictExportPresence); - dep.shorthand = parser.scope.inShorthand; - dep.directImport = false; - dep.loc = expr.loc; - parser.state.module.addDependency(dep); - return true; - }); - if(this.strictThisContextOnImports) { - // only in case when we strictly follow the spec we need a special case here - parser.hooks.callAnyMember.for("imported var").tap("HarmonyImportDependencyParserPlugin", (expr) => { - if(expr.callee.type !== "MemberExpression") return; - if(expr.callee.object.type !== "Identifier") return; - const name = expr.callee.object.name; + parser.hooks.import.tap( + "HarmonyImportDependencyParserPlugin", + (statement, source) => { + parser.state.lastHarmonyImportOrder = + (parser.state.lastHarmonyImportOrder || 0) + 1; + const clearDep = new ConstDependency("", statement.range); + clearDep.loc = statement.loc; + parser.state.module.addDependency(clearDep); + const sideEffectDep = new HarmonyImportSideEffectDependency( + source, + parser.state.module, + parser.state.lastHarmonyImportOrder, + parser.state.harmonyParserScope + ); + sideEffectDep.loc = statement.loc; + parser.state.module.addDependency(sideEffectDep); + return true; + } + ); + parser.hooks.importSpecifier.tap( + "HarmonyImportDependencyParserPlugin", + (statement, source, id, name) => { + parser.scope.definitions.delete(name); + parser.scope.renames.set(name, "imported var"); + if (!parser.state.harmonySpecifier) + parser.state.harmonySpecifier = new Map(); + parser.state.harmonySpecifier.set(name, { + source, + id, + sourceOrder: parser.state.lastHarmonyImportOrder + }); + return true; + } + ); + parser.hooks.expression + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + const name = expr.name; const settings = parser.state.harmonySpecifier.get(name); - if(settings.id !== null) - return false; - const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, expr.callee.property.name || expr.callee.property.value, name, expr.callee.range, this.strictExportPresence); + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + settings.id, + name, + expr.range, + this.strictExportPresence + ); dep.shorthand = parser.scope.inShorthand; - dep.directImport = false; - dep.namespaceObjectAsContext = true; - dep.loc = expr.callee.loc; + dep.directImport = true; + dep.loc = expr.loc; parser.state.module.addDependency(dep); - if(expr.arguments) - parser.walkExpressions(expr.arguments); return true; }); + parser.hooks.expressionAnyMember + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + const name = expr.object.name; + const settings = parser.state.harmonySpecifier.get(name); + if (settings.id !== null) return false; + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + expr.property.name || expr.property.value, + name, + expr.range, + this.strictExportPresence + ); + dep.shorthand = parser.scope.inShorthand; + dep.directImport = false; + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + return true; + }); + if (this.strictThisContextOnImports) { + // only in case when we strictly follow the spec we need a special case here + parser.hooks.callAnyMember + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + if (expr.callee.type !== "MemberExpression") return; + if (expr.callee.object.type !== "Identifier") return; + const name = expr.callee.object.name; + const settings = parser.state.harmonySpecifier.get(name); + if (settings.id !== null) return false; + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + expr.callee.property.name || expr.callee.property.value, + name, + expr.callee.range, + this.strictExportPresence + ); + dep.shorthand = parser.scope.inShorthand; + dep.directImport = false; + dep.namespaceObjectAsContext = true; + dep.loc = expr.callee.loc; + parser.state.module.addDependency(dep); + if (expr.arguments) parser.walkExpressions(expr.arguments); + return true; + }); } - parser.hooks.call.for("imported var").tap("HarmonyImportDependencyParserPlugin", (expr) => { - const args = expr.arguments; - const fullExpr = expr; - expr = expr.callee; - if(expr.type !== "Identifier") return; - const name = expr.name; - const settings = parser.state.harmonySpecifier.get(name); - const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, settings.id, name, expr.range, this.strictExportPresence); - dep.directImport = true; - dep.callArgs = args; - dep.call = fullExpr; - dep.loc = expr.loc; - parser.state.module.addDependency(dep); - if(args) - parser.walkExpressions(args); - return true; - }); + parser.hooks.call + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + const args = expr.arguments; + const fullExpr = expr; + expr = expr.callee; + if (expr.type !== "Identifier") return; + const name = expr.name; + const settings = parser.state.harmonySpecifier.get(name); + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + settings.id, + name, + expr.range, + this.strictExportPresence + ); + dep.directImport = true; + dep.callArgs = args; + dep.call = fullExpr; + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + if (args) parser.walkExpressions(args); + return true; + }); // TODO webpack 5: refactor this, no custom hooks - if(!parser.hooks.hotAcceptCallback) - parser.hooks.hotAcceptCallback = new SyncBailHook(["expression", "requests"]); - if(!parser.hooks.hotAcceptWithoutCallback) - parser.hooks.hotAcceptWithoutCallback = new SyncBailHook(["expression", "requests"]); - parser.hooks.hotAcceptCallback.tap("HarmonyImportDependencyParserPlugin", (expr, requests) => { - const dependencies = requests - .map(request => { - const dep = new HarmonyAcceptImportDependency(request, parser.state.module, parser.state.harmonyParserScope); + if (!parser.hooks.hotAcceptCallback) + parser.hooks.hotAcceptCallback = new SyncBailHook([ + "expression", + "requests" + ]); + if (!parser.hooks.hotAcceptWithoutCallback) + parser.hooks.hotAcceptWithoutCallback = new SyncBailHook([ + "expression", + "requests" + ]); + parser.hooks.hotAcceptCallback.tap( + "HarmonyImportDependencyParserPlugin", + (expr, requests) => { + const dependencies = requests.map(request => { + const dep = new HarmonyAcceptImportDependency( + request, + parser.state.module, + parser.state.harmonyParserScope + ); dep.loc = expr.loc; parser.state.module.addDependency(dep); return dep; }); - if(dependencies.length > 0) { - const dep = new HarmonyAcceptDependency(expr.range, dependencies, true); - dep.loc = expr.loc; - parser.state.module.addDependency(dep); + if (dependencies.length > 0) { + const dep = new HarmonyAcceptDependency( + expr.range, + dependencies, + true + ); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + } } - }); - parser.hooks.hotAcceptWithoutCallback.tap("HarmonyImportDependencyParserPlugin", (expr, requests) => { - const dependencies = requests - .map(request => { - const dep = new HarmonyAcceptImportDependency(request, parser.state.module, parser.state.harmonyParserScope); + ); + parser.hooks.hotAcceptWithoutCallback.tap( + "HarmonyImportDependencyParserPlugin", + (expr, requests) => { + const dependencies = requests.map(request => { + const dep = new HarmonyAcceptImportDependency( + request, + parser.state.module, + parser.state.harmonyParserScope + ); dep.loc = expr.loc; parser.state.module.addDependency(dep); return dep; }); - if(dependencies.length > 0) { - const dep = new HarmonyAcceptDependency(expr.range, dependencies, false); - dep.loc = expr.loc; - parser.state.module.addDependency(dep); + if (dependencies.length > 0) { + const dep = new HarmonyAcceptDependency( + expr.range, + dependencies, + false + ); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + } } - }); + ); } }; diff --git a/lib/dependencies/HarmonyImportSideEffectDependency.js b/lib/dependencies/HarmonyImportSideEffectDependency.js index 7b7e2b2ca..dcfb52499 100644 --- a/lib/dependencies/HarmonyImportSideEffectDependency.js +++ b/lib/dependencies/HarmonyImportSideEffectDependency.js @@ -11,7 +11,7 @@ class HarmonyImportSideEffectDependency extends HarmonyImportDependency { } getReference() { - if(this.module && this.module.factoryMeta.sideEffectFree) return null; + if (this.module && this.module.factoryMeta.sideEffectFree) return null; return super.getReference(); } @@ -23,7 +23,7 @@ class HarmonyImportSideEffectDependency extends HarmonyImportDependency { HarmonyImportSideEffectDependency.Template = class HarmonyImportSideEffectDependencyTemplate extends HarmonyImportDependency.Template { getHarmonyInitOrder(dep) { - if(dep.module && dep.module.factoryMeta.sideEffectFree) return NaN; + if (dep.module && dep.module.factoryMeta.sideEffectFree) return NaN; return super.getHarmonyInitOrder(dep); } }; diff --git a/lib/dependencies/HarmonyImportSpecifierDependency.js b/lib/dependencies/HarmonyImportSpecifierDependency.js index 6760bc58d..fdef9152c 100644 --- a/lib/dependencies/HarmonyImportSpecifierDependency.js +++ b/lib/dependencies/HarmonyImportSpecifierDependency.js @@ -6,7 +6,16 @@ const HarmonyImportDependency = require("./HarmonyImportDependency"); class HarmonyImportSpecifierDependency extends HarmonyImportDependency { - constructor(request, originModule, sourceOrder, parserScope, id, name, range, strictExportPresence) { + constructor( + request, + originModule, + sourceOrder, + parserScope, + id, + name, + range, + strictExportPresence + ) { super(request, originModule, sourceOrder, parserScope); this.id = id === null ? null : `${id}`; this.name = name; @@ -23,22 +32,29 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { } getReference() { - if(!this.module) return null; + if (!this.module) return null; return { module: this.module, - importedNames: this.id && !this.namespaceObjectAsContext ? [this.id] : true + importedNames: + this.id && !this.namespaceObjectAsContext ? [this.id] : true }; } getWarnings() { - if(this.strictExportPresence || this.originModule.buildMeta.strictHarmonyModule) { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { return []; } return this._getErrors(); } getErrors() { - if(this.strictExportPresence || this.originModule.buildMeta.strictHarmonyModule) { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { return this._getErrors(); } return []; @@ -46,34 +62,46 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { _getErrors() { const importedModule = this.module; - if(!importedModule) { + if (!importedModule) { return; } - if(!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { + if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { // It's not an harmony module - if(this.originModule.buildMeta.strictHarmonyModule && this.id !== "default") { + if ( + this.originModule.buildMeta.strictHarmonyModule && + this.id !== "default" + ) { // In strict harmony modules we only support the default export - const exportName = this.id ? `the named export '${this.id}'` : "the namespace object"; - const err = new Error(`Can't import ${exportName} from non EcmaScript module (only default export is available)`); + const exportName = this.id + ? `the named export '${this.id}'` + : "the namespace object"; + const err = new Error( + `Can't import ${ + exportName + } from non EcmaScript module (only default export is available)` + ); err.hideStack = true; return [err]; } return; } - if(!this.id) { + if (!this.id) { return; } - if(importedModule.isProvided(this.id) !== false) { + if (importedModule.isProvided(this.id) !== false) { // It's provided or we are not sure return; } // We are sure that it's not provided - const idIsNotNameMessage = this.id !== this.name ? ` (imported as '${this.name}')` : ""; - const errorMessage = `"export '${this.id}'${idIsNotNameMessage} was not found in '${this.userRequest}'`; + const idIsNotNameMessage = + this.id !== this.name ? ` (imported as '${this.name}')` : ""; + const errorMessage = `"export '${this.id}'${ + idIsNotNameMessage + } was not found in '${this.userRequest}'`; const err = new Error(errorMessage); err.hideStack = true; return [err]; @@ -88,9 +116,18 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { super.updateHash(hash); const importedModule = this.module; hash.update((importedModule && this.id) + ""); - hash.update((importedModule && this.id && importedModule.isUsed(this.id)) + ""); - hash.update((importedModule && (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + ""); - hash.update((importedModule && (importedModule.used + JSON.stringify(importedModule.usedExports))) + ""); + hash.update( + (importedModule && this.id && importedModule.isUsed(this.id)) + "" + ); + hash.update( + (importedModule && + (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + + "" + ); + hash.update( + (importedModule && + importedModule.used + JSON.stringify(importedModule.usedExports)) + "" + ); } } diff --git a/lib/dependencies/HarmonyInitDependency.js b/lib/dependencies/HarmonyInitDependency.js index 68b2c0543..73239c8b9 100644 --- a/lib/dependencies/HarmonyInitDependency.js +++ b/lib/dependencies/HarmonyInitDependency.js @@ -23,16 +23,20 @@ HarmonyInitDependency.Template = class HarmonyInitDependencyTemplate { apply(dep, source, runtime, dependencyTemplates) { const module = dep.originModule; const list = []; - for(const dependency of module.dependencies) { + for (const dependency of module.dependencies) { const template = dependencyTemplates.get(dependency.constructor); - if(template && typeof template.harmonyInit === "function" && typeof template.getHarmonyInitOrder === "function") { + if ( + template && + typeof template.harmonyInit === "function" && + typeof template.getHarmonyInitOrder === "function" + ) { const order = template.getHarmonyInitOrder(dependency); - if(!isNaN(order)) { + if (!isNaN(order)) { list.push({ order, listOrder: list.length, dependency, - template, + template }); } } @@ -40,12 +44,17 @@ HarmonyInitDependency.Template = class HarmonyInitDependencyTemplate { list.sort((a, b) => { const x = a.order - b.order; - if(x) return x; + if (x) return x; return a.listOrder - b.listOrder; }); - for(const item of list) { - item.template.harmonyInit(item.dependency, source, runtime, dependencyTemplates); + for (const item of list) { + item.template.harmonyInit( + item.dependency, + source, + runtime, + dependencyTemplates + ); } } }; diff --git a/lib/dependencies/HarmonyModulesPlugin.js b/lib/dependencies/HarmonyModulesPlugin.js index a43166d91..12a50a25a 100644 --- a/lib/dependencies/HarmonyModulesPlugin.js +++ b/lib/dependencies/HarmonyModulesPlugin.js @@ -27,52 +27,120 @@ class HarmonyModulesPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("HarmonyModulesPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(HarmonyCompatibilityDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyCompatibilityDependency, new HarmonyCompatibilityDependency.Template()); + compiler.hooks.compilation.tap( + "HarmonyModulesPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + HarmonyCompatibilityDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyCompatibilityDependency, + new HarmonyCompatibilityDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyInitDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyInitDependency, new HarmonyInitDependency.Template()); + compilation.dependencyFactories.set( + HarmonyInitDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyInitDependency, + new HarmonyInitDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyImportSideEffectDependency, normalModuleFactory); - compilation.dependencyTemplates.set(HarmonyImportSideEffectDependency, new HarmonyImportSideEffectDependency.Template()); + compilation.dependencyFactories.set( + HarmonyImportSideEffectDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyImportSideEffectDependency, + new HarmonyImportSideEffectDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyImportSpecifierDependency, normalModuleFactory); - compilation.dependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependency.Template()); + compilation.dependencyFactories.set( + HarmonyImportSpecifierDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyImportSpecifierDependency, + new HarmonyImportSpecifierDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyExportHeaderDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportHeaderDependency, new HarmonyExportHeaderDependency.Template()); + compilation.dependencyFactories.set( + HarmonyExportHeaderDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyExportHeaderDependency, + new HarmonyExportHeaderDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyExportExpressionDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportExpressionDependency, new HarmonyExportExpressionDependency.Template()); + compilation.dependencyFactories.set( + HarmonyExportExpressionDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyExportExpressionDependency, + new HarmonyExportExpressionDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyExportSpecifierDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependency.Template()); + compilation.dependencyFactories.set( + HarmonyExportSpecifierDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyExportSpecifierDependency, + new HarmonyExportSpecifierDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyExportImportedSpecifierDependency, normalModuleFactory); - compilation.dependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependency.Template()); + compilation.dependencyFactories.set( + HarmonyExportImportedSpecifierDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyExportImportedSpecifierDependency, + new HarmonyExportImportedSpecifierDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyAcceptDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyAcceptDependency, new HarmonyAcceptDependency.Template()); + compilation.dependencyFactories.set( + HarmonyAcceptDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyAcceptDependency, + new HarmonyAcceptDependency.Template() + ); - compilation.dependencyFactories.set(HarmonyAcceptImportDependency, normalModuleFactory); - compilation.dependencyTemplates.set(HarmonyAcceptImportDependency, new HarmonyAcceptImportDependency.Template()); + compilation.dependencyFactories.set( + HarmonyAcceptImportDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyAcceptImportDependency, + new HarmonyAcceptImportDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.harmony !== "undefined" && !parserOptions.harmony) - return; + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.harmony !== "undefined" && + !parserOptions.harmony + ) + return; - new HarmonyDetectionParserPlugin().apply(parser); - new HarmonyImportDependencyParserPlugin(this.options).apply(parser); - new HarmonyExportDependencyParserPlugin(this.options).apply(parser); - new HarmonyTopLevelThisParserPlugin().apply(parser); - }; + new HarmonyDetectionParserPlugin().apply(parser); + new HarmonyImportDependencyParserPlugin(this.options).apply(parser); + new HarmonyExportDependencyParserPlugin(this.options).apply(parser); + new HarmonyTopLevelThisParserPlugin().apply(parser); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("HarmonyModulesPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("HarmonyModulesPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("HarmonyModulesPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("HarmonyModulesPlugin", handler); + } + ); } } module.exports = HarmonyModulesPlugin; diff --git a/lib/dependencies/HarmonyTopLevelThisParserPlugin.js b/lib/dependencies/HarmonyTopLevelThisParserPlugin.js index 22de77725..f03600930 100644 --- a/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +++ b/lib/dependencies/HarmonyTopLevelThisParserPlugin.js @@ -8,17 +8,18 @@ const ConstDependency = require("./ConstDependency"); class HarmonyTopLevelThisParserPlugin { apply(parser) { - parser.hooks.expression.for("this").tap("HarmonyTopLevelThisParserPlugin", node => { - if(!parser.scope.topLevelScope) - return; - const module = parser.state.module; - const isHarmony = !!(module.buildMeta && module.buildMeta.exportsType); - if(isHarmony) { - const dep = new ConstDependency("undefined", node.range, false); - dep.loc = node.loc; - parser.state.current.addDependency(dep); - } - }); + parser.hooks.expression + .for("this") + .tap("HarmonyTopLevelThisParserPlugin", node => { + if (!parser.scope.topLevelScope) return; + const module = parser.state.module; + const isHarmony = !!(module.buildMeta && module.buildMeta.exportsType); + if (isHarmony) { + const dep = new ConstDependency("undefined", node.range, false); + dep.loc = node.loc; + parser.state.current.addDependency(dep); + } + }); } } diff --git a/lib/dependencies/ImportContextDependency.js b/lib/dependencies/ImportContextDependency.js index ae62cde6e..f25a28a15 100644 --- a/lib/dependencies/ImportContextDependency.js +++ b/lib/dependencies/ImportContextDependency.js @@ -16,7 +16,6 @@ class ImportContextDependency extends ContextDependency { get type() { return `import() context ${this.options.mode}`; } - } ImportContextDependency.Template = ContextDependencyTemplateAsRequireCall; diff --git a/lib/dependencies/ImportParserPlugin.js b/lib/dependencies/ImportParserPlugin.js index 64e247852..435692931 100644 --- a/lib/dependencies/ImportParserPlugin.js +++ b/lib/dependencies/ImportParserPlugin.js @@ -18,8 +18,10 @@ class ImportParserPlugin { apply(parser) { parser.hooks.importCall.tap("ImportParserPlugin", expr => { - if(expr.arguments.length !== 1) - throw new Error("Incorrect number of arguments provided to 'import(module: string) -> Promise'."); + if (expr.arguments.length !== 1) + throw new Error( + "Incorrect number of arguments provided to 'import(module: string) -> Promise'." + ); const param = parser.evaluateExpression(expr.arguments[0]); @@ -29,68 +31,143 @@ class ImportParserPlugin { let exclude = null; const importOptions = parser.getCommentOptions(expr.range); - if(importOptions) { - if(typeof importOptions.webpackChunkName !== "undefined") { - if(typeof importOptions.webpackChunkName !== "string") - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`)); - else - chunkName = importOptions.webpackChunkName; + if (importOptions) { + if (typeof importOptions.webpackChunkName !== "undefined") { + if (typeof importOptions.webpackChunkName !== "string") + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackChunkName\` expected a string, but received: ${ + importOptions.webpackChunkName + }.` + ) + ); + else chunkName = importOptions.webpackChunkName; } - if(typeof importOptions.webpackMode !== "undefined") { - if(typeof importOptions.webpackMode !== "string") - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`)); - else - mode = importOptions.webpackMode; + if (typeof importOptions.webpackMode !== "undefined") { + if (typeof importOptions.webpackMode !== "string") + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackMode\` expected a string, but received: ${ + importOptions.webpackMode + }.` + ) + ); + else mode = importOptions.webpackMode; } - if(typeof importOptions.webpackInclude !== "undefined") { - if(!importOptions.webpackInclude || importOptions.webpackInclude.constructor.name !== "RegExp") { - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackInclude\` expected a regular expression, but received: ${importOptions.webpackInclude}.`)); + if (typeof importOptions.webpackInclude !== "undefined") { + if ( + !importOptions.webpackInclude || + importOptions.webpackInclude.constructor.name !== "RegExp" + ) { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackInclude\` expected a regular expression, but received: ${ + importOptions.webpackInclude + }.` + ) + ); } else { include = new RegExp(importOptions.webpackInclude); } } - if(typeof importOptions.webpackExclude !== "undefined") { - if(!importOptions.webpackExclude || importOptions.webpackExclude.constructor.name !== "RegExp") { - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackExclude\` expected a regular expression, but received: ${importOptions.webpackExclude}.`)); + if (typeof importOptions.webpackExclude !== "undefined") { + if ( + !importOptions.webpackExclude || + importOptions.webpackExclude.constructor.name !== "RegExp" + ) { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackExclude\` expected a regular expression, but received: ${ + importOptions.webpackExclude + }.` + ) + ); } else { exclude = new RegExp(importOptions.webpackExclude); } } } - if(param.isString()) { - if(mode !== "lazy" && mode !== "eager" && mode !== "weak") { - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`)); + if (param.isString()) { + if (mode !== "lazy" && mode !== "eager" && mode !== "weak") { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${ + mode + }.` + ) + ); } - if(mode === "eager") { - const dep = new ImportEagerDependency(param.string, parser.state.module, expr.range); + if (mode === "eager") { + const dep = new ImportEagerDependency( + param.string, + parser.state.module, + expr.range + ); parser.state.current.addDependency(dep); - } else if(mode === "weak") { - const dep = new ImportWeakDependency(param.string, parser.state.module, expr.range); + } else if (mode === "weak") { + const dep = new ImportWeakDependency( + param.string, + parser.state.module, + expr.range + ); parser.state.current.addDependency(dep); } else { - const depBlock = new ImportDependenciesBlock(param.string, expr.range, chunkName, parser.state.module, expr.loc, parser.state.module); + const depBlock = new ImportDependenciesBlock( + param.string, + expr.range, + chunkName, + parser.state.module, + expr.loc, + parser.state.module + ); parser.state.current.addBlock(depBlock); } return true; } else { - if(mode !== "lazy" && mode !== "lazy-once" && mode !== "eager" && mode !== "weak") { - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`)); + if ( + mode !== "lazy" && + mode !== "lazy-once" && + mode !== "eager" && + mode !== "weak" + ) { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${ + mode + }.` + ) + ); mode = "lazy"; } - if(mode === "weak") { + if (mode === "weak") { mode = "async-weak"; } - const dep = ContextDependencyHelpers.create(ImportContextDependency, expr.range, param, expr, this.options, { - chunkName, - include, - exclude, - mode, - namespaceObject: parser.state.module.buildMeta.strictHarmonyModule ? "strict" : true - }); - if(!dep) return; + const dep = ContextDependencyHelpers.create( + ImportContextDependency, + expr.range, + param, + expr, + this.options, + { + chunkName, + include, + exclude, + mode, + namespaceObject: parser.state.module.buildMeta.strictHarmonyModule + ? "strict" + : true + } + ); + if (!dep) return; dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); diff --git a/lib/dependencies/ImportPlugin.js b/lib/dependencies/ImportPlugin.js index f2f05d160..8d488e0d9 100644 --- a/lib/dependencies/ImportPlugin.js +++ b/lib/dependencies/ImportPlugin.js @@ -17,33 +17,66 @@ class ImportPlugin { apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("ImportPlugin", (compilation, { - contextModuleFactory, - normalModuleFactory - }) => { - compilation.dependencyFactories.set(ImportDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ImportDependency, new ImportDependency.Template()); + compiler.hooks.compilation.tap( + "ImportPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + ImportDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ImportDependency, + new ImportDependency.Template() + ); - compilation.dependencyFactories.set(ImportEagerDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ImportEagerDependency, new ImportEagerDependency.Template()); + compilation.dependencyFactories.set( + ImportEagerDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ImportEagerDependency, + new ImportEagerDependency.Template() + ); - compilation.dependencyFactories.set(ImportWeakDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ImportWeakDependency, new ImportWeakDependency.Template()); + compilation.dependencyFactories.set( + ImportWeakDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ImportWeakDependency, + new ImportWeakDependency.Template() + ); - compilation.dependencyFactories.set(ImportContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(ImportContextDependency, new ImportContextDependency.Template()); + compilation.dependencyFactories.set( + ImportContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + ImportContextDependency, + new ImportContextDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.import !== "undefined" && !parserOptions.import) - return; + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.import !== "undefined" && + !parserOptions.import + ) + return; - new ImportParserPlugin(options).apply(parser); - }; + new ImportParserPlugin(options).apply(parser); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("ImportPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ImportPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("ImportPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ImportPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ImportPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ImportPlugin", handler); + } + ); } } module.exports = ImportPlugin; diff --git a/lib/dependencies/LoaderPlugin.js b/lib/dependencies/LoaderPlugin.js index 2a1d8854d..ec0a22631 100644 --- a/lib/dependencies/LoaderPlugin.js +++ b/lib/dependencies/LoaderPlugin.js @@ -7,56 +7,83 @@ const LoaderDependency = require("./LoaderDependency"); class LoaderPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("LoaderPlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(LoaderDependency, normalModuleFactory); - }); + compiler.hooks.compilation.tap( + "LoaderPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + LoaderDependency, + normalModuleFactory + ); + } + ); - compiler.hooks.compilation.tap("LoaderPlugin", (compilation) => { - compilation.hooks.normalModuleLoader.tap("LoaderPlugin", (loaderContext, module) => { - loaderContext.loadModule = (request, callback) => { - const dep = new LoaderDependency(request); - dep.loc = request; - const factory = compilation.dependencyFactories.get(dep.constructor); - if(factory === undefined) - return callback(new Error(`No module factory available for dependency type: ${dep.constructor.name}`)); - compilation.addModuleDependencies(module, [{ - factory, - dependencies: [dep] - }], true, "lm", false, err => { - if(err) return callback(err); + compiler.hooks.compilation.tap("LoaderPlugin", compilation => { + compilation.hooks.normalModuleLoader.tap( + "LoaderPlugin", + (loaderContext, module) => { + loaderContext.loadModule = (request, callback) => { + const dep = new LoaderDependency(request); + dep.loc = request; + const factory = compilation.dependencyFactories.get( + dep.constructor + ); + if (factory === undefined) + return callback( + new Error( + `No module factory available for dependency type: ${ + dep.constructor.name + }` + ) + ); + compilation.addModuleDependencies( + module, + [ + { + factory, + dependencies: [dep] + } + ], + true, + "lm", + false, + err => { + if (err) return callback(err); - if(!dep.module) return callback(new Error("Cannot load the module")); + if (!dep.module) + return callback(new Error("Cannot load the module")); - if(dep.module.error) return callback(dep.module.error); - if(!dep.module._source) throw new Error("The module created for a LoaderDependency must have a property _source"); - let source, map; - const moduleSource = dep.module._source; - if(moduleSource.sourceAndMap) { - const sourceAndMap = moduleSource.sourceAndMap(); - map = sourceAndMap.map; - source = sourceAndMap.source; - } else { - map = moduleSource.map(); - source = moduleSource.source(); - } - if(dep.module.buildInfo.fileDependencies) { - for(const d of dep.module.buildInfo.fileDependencies) { - loaderContext.addDependency(d); + if (dep.module.error) return callback(dep.module.error); + if (!dep.module._source) + throw new Error( + "The module created for a LoaderDependency must have a property _source" + ); + let source, map; + const moduleSource = dep.module._source; + if (moduleSource.sourceAndMap) { + const sourceAndMap = moduleSource.sourceAndMap(); + map = sourceAndMap.map; + source = sourceAndMap.source; + } else { + map = moduleSource.map(); + source = moduleSource.source(); + } + if (dep.module.buildInfo.fileDependencies) { + for (const d of dep.module.buildInfo.fileDependencies) { + loaderContext.addDependency(d); + } + } + if (dep.module.buildInfo.contextDependencies) { + for (const d of dep.module.buildInfo.contextDependencies) { + loaderContext.addContextDependency(d); + } + } + return callback(null, source, map, dep.module); } - } - if(dep.module.buildInfo.contextDependencies) { - for(const d of dep.module.buildInfo.contextDependencies) { - loaderContext.addContextDependency(d); - } - } - return callback(null, source, map, dep.module); - }); - }; - }); + ); + }; + } + ); }); } } diff --git a/lib/dependencies/LocalModuleDependency.js b/lib/dependencies/LocalModuleDependency.js index 7de45c2f1..1a97fe396 100644 --- a/lib/dependencies/LocalModuleDependency.js +++ b/lib/dependencies/LocalModuleDependency.js @@ -16,8 +16,12 @@ class LocalModuleDependency extends NullDependency { LocalModuleDependency.Template = class LocalModuleDependencyTemplate { apply(dep, source) { - if(!dep.range) return; - source.replace(dep.range[0], dep.range[1] - 1, dep.localModule.variableName()); + if (!dep.range) return; + source.replace( + dep.range[0], + dep.range[1] - 1, + dep.localModule.variableName() + ); } }; diff --git a/lib/dependencies/LocalModulesHelpers.js b/lib/dependencies/LocalModulesHelpers.js index c5097cc97..73de4b971 100644 --- a/lib/dependencies/LocalModulesHelpers.js +++ b/lib/dependencies/LocalModulesHelpers.js @@ -8,37 +8,36 @@ const LocalModule = require("./LocalModule"); const LocalModulesHelpers = exports; const lookup = (parent, mod) => { - if(mod.charAt(0) !== ".") return mod; + if (mod.charAt(0) !== ".") return mod; var path = parent.split("/"), segs = mod.split("/"); path.pop(); - for(let i = 0; i < segs.length; i++) { + for (let i = 0; i < segs.length; i++) { const seg = segs[i]; - if(seg === "..") path.pop(); - else if(seg !== ".") path.push(seg); + if (seg === "..") path.pop(); + else if (seg !== ".") path.push(seg); } return path.join("/"); }; LocalModulesHelpers.addLocalModule = (state, name) => { - if(!state.localModules) state.localModules = []; + if (!state.localModules) state.localModules = []; const m = new LocalModule(state.module, name, state.localModules.length); state.localModules.push(m); return m; }; LocalModulesHelpers.getLocalModule = (state, name, namedModule) => { - if(!state.localModules) return null; - if(namedModule) { + if (!state.localModules) return null; + if (namedModule) { // resolve dependency name relative to the defining named module name = lookup(namedModule, name); } - for(let i = 0; i < state.localModules.length; i++) { - if(state.localModules[i].name === name) - return state.localModules[i]; + for (let i = 0; i < state.localModules.length; i++) { + if (state.localModules[i].name === name) return state.localModules[i]; } return null; }; diff --git a/lib/dependencies/ModuleDependencyTemplateAsId.js b/lib/dependencies/ModuleDependencyTemplateAsId.js index bf05c3055..82bc6b5d6 100644 --- a/lib/dependencies/ModuleDependencyTemplateAsId.js +++ b/lib/dependencies/ModuleDependencyTemplateAsId.js @@ -5,9 +5,8 @@ "use strict"; class ModuleDependencyTemplateAsId { - apply(dep, source, runtime) { - if(!dep.range) return; + if (!dep.range) return; const content = runtime.moduleId({ module: dep.module, request: dep.request diff --git a/lib/dependencies/ModuleDependencyTemplateAsRequireId.js b/lib/dependencies/ModuleDependencyTemplateAsRequireId.js index 2196890d1..db74b895f 100644 --- a/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +++ b/lib/dependencies/ModuleDependencyTemplateAsRequireId.js @@ -5,9 +5,8 @@ "use strict"; class ModuleDependencyTemplateAsRequireId { - apply(dep, source, runtime) { - if(!dep.range) return; + if (!dep.range) return; const content = runtime.moduleExports({ module: dep.module, request: dep.request diff --git a/lib/dependencies/RequireContextDependencyParserPlugin.js b/lib/dependencies/RequireContextDependencyParserPlugin.js index e88c66e53..1071fc01d 100644 --- a/lib/dependencies/RequireContextDependencyParserPlugin.js +++ b/lib/dependencies/RequireContextDependencyParserPlugin.js @@ -8,48 +8,49 @@ const RequireContextDependency = require("./RequireContextDependency"); module.exports = class RequireContextDependencyParserPlugin { apply(parser) { - parser.hooks.call.for("require.context").tap("RequireContextDependencyParserPlugin", expr => { - let regExp = /^\.\/.*$/; - let recursive = true; - let mode = "sync"; - switch(expr.arguments.length) { - case 4: - { + parser.hooks.call + .for("require.context") + .tap("RequireContextDependencyParserPlugin", expr => { + let regExp = /^\.\/.*$/; + let recursive = true; + let mode = "sync"; + switch (expr.arguments.length) { + case 4: { const modeExpr = parser.evaluateExpression(expr.arguments[3]); - if(!modeExpr.isString()) return; + if (!modeExpr.isString()) return; mode = modeExpr.string; } // falls through - case 3: - { + case 3: { const regExpExpr = parser.evaluateExpression(expr.arguments[2]); - if(!regExpExpr.isRegExp()) return; + if (!regExpExpr.isRegExp()) return; regExp = regExpExpr.regExp; } // falls through - case 2: - { + case 2: { const recursiveExpr = parser.evaluateExpression(expr.arguments[1]); - if(!recursiveExpr.isBoolean()) return; + if (!recursiveExpr.isBoolean()) return; recursive = recursiveExpr.bool; } // falls through - case 1: - { + case 1: { const requestExpr = parser.evaluateExpression(expr.arguments[0]); - if(!requestExpr.isString()) return; - const dep = new RequireContextDependency({ - request: requestExpr.string, - recursive, - regExp, - mode - }, expr.range); + if (!requestExpr.isString()) return; + const dep = new RequireContextDependency( + { + request: requestExpr.string, + recursive, + regExp, + mode + }, + expr.range + ); dep.loc = expr.loc; dep.optional = parser.scope.inTry; parser.state.current.addDependency(dep); return true; } - } - }); + } + }); } }; diff --git a/lib/dependencies/RequireContextPlugin.js b/lib/dependencies/RequireContextPlugin.js index 35e369699..549ba5c99 100644 --- a/lib/dependencies/RequireContextPlugin.js +++ b/lib/dependencies/RequireContextPlugin.js @@ -11,9 +11,9 @@ const RequireContextDependencyParserPlugin = require("./RequireContextDependency class RequireContextPlugin { constructor(modulesDirectories, extensions, mainFiles) { - if(!Array.isArray(modulesDirectories)) + if (!Array.isArray(modulesDirectories)) throw new Error("modulesDirectories must be an array"); - if(!Array.isArray(extensions)) + if (!Array.isArray(extensions)) throw new Error("extensions must be an array"); this.modulesDirectories = modulesDirectories; this.extensions = extensions; @@ -21,75 +21,121 @@ class RequireContextPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("RequireContextPlugin", (compilation, { - contextModuleFactory, - normalModuleFactory - }) => { - compilation.dependencyFactories.set(RequireContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(RequireContextDependency, new RequireContextDependency.Template()); + compiler.hooks.compilation.tap( + "RequireContextPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + RequireContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + RequireContextDependency, + new RequireContextDependency.Template() + ); - compilation.dependencyFactories.set(ContextElementDependency, normalModuleFactory); + compilation.dependencyFactories.set( + ContextElementDependency, + normalModuleFactory + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.requireContext !== "undefined" && !parserOptions.requireContext) - return; + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.requireContext !== "undefined" && + !parserOptions.requireContext + ) + return; - new RequireContextDependencyParserPlugin().apply(parser); - }; + new RequireContextDependencyParserPlugin().apply(parser); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("RequireContextPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("RequireContextPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireContextPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireContextPlugin", handler); - contextModuleFactory.hooks.alternatives.tap("RequireContextPlugin", (items) => { - if(items.length === 0) return items; - return items.map((obj) => { - return this.extensions.filter((ext) => { - const l = obj.request.length; - return l > ext.length && obj.request.substr(l - ext.length, l) === ext; - }).map((ext) => { - const l = obj.request.length; - return { - context: obj.context, - request: obj.request.substr(0, l - ext.length) - }; - }).concat(obj); - }).reduce((a, b) => a.concat(b), []); - }); - - contextModuleFactory.hooks.alternatives.tap("RequireContextPlugin", (items) => { - if(items.length === 0) return items; - return items.map((obj) => { - return this.mainFiles.filter((mainFile) => { - const l = obj.request.length; - return l > mainFile.length + 1 && obj.request.substr(l - mainFile.length - 1, l) === "/" + mainFile; - }).map((mainFile) => { - const l = obj.request.length; - return [{ - context: obj.context, - request: obj.request.substr(0, l - mainFile.length) - }, { - context: obj.context, - request: obj.request.substr(0, l - mainFile.length - 1) - }]; - }).reduce((a, b) => a.concat(b), []).concat(obj); - }).reduce((a, b) => a.concat(b), []); - }); - - contextModuleFactory.hooks.alternatives.tap("RequireContextPlugin", (items) => { - if(items.length === 0) return items; - return items.map((obj) => { - for(let i = 0; i < this.modulesDirectories.length; i++) { - const dir = this.modulesDirectories[i]; - const idx = obj.request.indexOf("./" + dir + "/"); - if(idx === 0) { - obj.request = obj.request.slice(dir.length + 3); - break; - } + contextModuleFactory.hooks.alternatives.tap( + "RequireContextPlugin", + items => { + if (items.length === 0) return items; + return items + .map(obj => { + return this.extensions + .filter(ext => { + const l = obj.request.length; + return ( + l > ext.length && + obj.request.substr(l - ext.length, l) === ext + ); + }) + .map(ext => { + const l = obj.request.length; + return { + context: obj.context, + request: obj.request.substr(0, l - ext.length) + }; + }) + .concat(obj); + }) + .reduce((a, b) => a.concat(b), []); } - return obj; - }); - }); - }); + ); + + contextModuleFactory.hooks.alternatives.tap( + "RequireContextPlugin", + items => { + if (items.length === 0) return items; + return items + .map(obj => { + return this.mainFiles + .filter(mainFile => { + const l = obj.request.length; + return ( + l > mainFile.length + 1 && + obj.request.substr(l - mainFile.length - 1, l) === + "/" + mainFile + ); + }) + .map(mainFile => { + const l = obj.request.length; + return [ + { + context: obj.context, + request: obj.request.substr(0, l - mainFile.length) + }, + { + context: obj.context, + request: obj.request.substr(0, l - mainFile.length - 1) + } + ]; + }) + .reduce((a, b) => a.concat(b), []) + .concat(obj); + }) + .reduce((a, b) => a.concat(b), []); + } + ); + + contextModuleFactory.hooks.alternatives.tap( + "RequireContextPlugin", + items => { + if (items.length === 0) return items; + return items.map(obj => { + for (let i = 0; i < this.modulesDirectories.length; i++) { + const dir = this.modulesDirectories[i]; + const idx = obj.request.indexOf("./" + dir + "/"); + if (idx === 0) { + obj.request = obj.request.slice(dir.length + 3); + break; + } + } + return obj; + }); + } + ); + } + ); } } module.exports = RequireContextPlugin; diff --git a/lib/dependencies/RequireEnsureDependenciesBlock.js b/lib/dependencies/RequireEnsureDependenciesBlock.js index f4f4f72dc..2a5dde704 100644 --- a/lib/dependencies/RequireEnsureDependenciesBlock.js +++ b/lib/dependencies/RequireEnsureDependenciesBlock.js @@ -7,11 +7,22 @@ const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); const RequireEnsureDependency = require("./RequireEnsureDependency"); module.exports = class RequireEnsureDependenciesBlock extends AsyncDependenciesBlock { - constructor(expr, successExpression, errorExpression, chunkName, chunkNameRange, module, loc) { + constructor( + expr, + successExpression, + errorExpression, + chunkName, + chunkNameRange, + module, + loc + ) { super(chunkName, module, loc, null); this.expr = expr; - const successBodyRange = successExpression && successExpression.body && successExpression.body.range; - if(successBodyRange) { + const successBodyRange = + successExpression && + successExpression.body && + successExpression.body.range; + if (successBodyRange) { this.range = [successBodyRange[0] + 1, successBodyRange[1] - 1]; } this.chunkNameRange = chunkNameRange; diff --git a/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js b/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js index ece0c5896..8df843dfa 100644 --- a/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +++ b/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js @@ -10,59 +10,74 @@ const getFunctionExpression = require("./getFunctionExpression"); module.exports = class RequireEnsureDependenciesBlockParserPlugin { apply(parser) { - parser.hooks.call.for("require.ensure").tap("RequireEnsureDependenciesBlockParserPlugin", expr => { - let chunkName = null; - let chunkNameRange = null; - let errorExpressionArg = null; - let errorExpression = null; - switch(expr.arguments.length) { - case 4: - { + parser.hooks.call + .for("require.ensure") + .tap("RequireEnsureDependenciesBlockParserPlugin", expr => { + let chunkName = null; + let chunkNameRange = null; + let errorExpressionArg = null; + let errorExpression = null; + switch (expr.arguments.length) { + case 4: { const chunkNameExpr = parser.evaluateExpression(expr.arguments[3]); - if(!chunkNameExpr.isString()) return; + if (!chunkNameExpr.isString()) return; chunkNameRange = chunkNameExpr.range; chunkName = chunkNameExpr.string; } // falls through - case 3: - { + case 3: { errorExpressionArg = expr.arguments[2]; errorExpression = getFunctionExpression(errorExpressionArg); - if(!errorExpression && !chunkName) { - const chunkNameExpr = parser.evaluateExpression(expr.arguments[2]); - if(!chunkNameExpr.isString()) return; + if (!errorExpression && !chunkName) { + const chunkNameExpr = parser.evaluateExpression( + expr.arguments[2] + ); + if (!chunkNameExpr.isString()) return; chunkNameRange = chunkNameExpr.range; chunkName = chunkNameExpr.string; } } // falls through - case 2: - { - const dependenciesExpr = parser.evaluateExpression(expr.arguments[0]); - const dependenciesItems = dependenciesExpr.isArray() ? dependenciesExpr.items : [dependenciesExpr]; + case 2: { + const dependenciesExpr = parser.evaluateExpression( + expr.arguments[0] + ); + const dependenciesItems = dependenciesExpr.isArray() + ? dependenciesExpr.items + : [dependenciesExpr]; const successExpressionArg = expr.arguments[1]; - const successExpression = getFunctionExpression(successExpressionArg); + const successExpression = getFunctionExpression( + successExpressionArg + ); - if(successExpression) { + if (successExpression) { parser.walkExpressions(successExpression.expressions); } - if(errorExpression) { + if (errorExpression) { parser.walkExpressions(errorExpression.expressions); } - const dep = new RequireEnsureDependenciesBlock(expr, + const dep = new RequireEnsureDependenciesBlock( + expr, successExpression ? successExpression.fn : successExpressionArg, errorExpression ? errorExpression.fn : errorExpressionArg, - chunkName, chunkNameRange, parser.state.module, expr.loc); + chunkName, + chunkNameRange, + parser.state.module, + expr.loc + ); const old = parser.state.current; parser.state.current = dep; try { let failed = false; parser.inScope([], () => { - for(const ee of dependenciesItems) { - if(ee.isString()) { - const edep = new RequireEnsureItemDependency(ee.string, ee.range); + for (const ee of dependenciesItems) { + if (ee.isString()) { + const edep = new RequireEnsureItemDependency( + ee.string, + ee.range + ); edep.loc = dep.loc; dep.addDependency(edep); } else { @@ -70,33 +85,31 @@ module.exports = class RequireEnsureDependenciesBlockParserPlugin { } } }); - if(failed) { + if (failed) { return; } - if(successExpression) { - if(successExpression.fn.body.type === "BlockStatement") + if (successExpression) { + if (successExpression.fn.body.type === "BlockStatement") parser.walkStatement(successExpression.fn.body); - else - parser.walkExpression(successExpression.fn.body); + else parser.walkExpression(successExpression.fn.body); } old.addBlock(dep); } finally { parser.state.current = old; } - if(!successExpression) { + if (!successExpression) { parser.walkExpression(successExpressionArg); } - if(errorExpression) { - if(errorExpression.fn.body.type === "BlockStatement") + if (errorExpression) { + if (errorExpression.fn.body.type === "BlockStatement") parser.walkStatement(errorExpression.fn.body); - else - parser.walkExpression(errorExpression.fn.body); - } else if(errorExpressionArg) { + else parser.walkExpression(errorExpression.fn.body); + } else if (errorExpressionArg) { parser.walkExpression(errorExpressionArg); } return true; } - } - }); + } + }); } }; diff --git a/lib/dependencies/RequireEnsureDependency.js b/lib/dependencies/RequireEnsureDependency.js index 6e22bd7da..840130519 100644 --- a/lib/dependencies/RequireEnsureDependency.js +++ b/lib/dependencies/RequireEnsureDependency.js @@ -23,16 +23,34 @@ RequireEnsureDependency.Template = class RequireEnsureDependencyTemplate { block: depBlock, message: "require.ensure" }); - const errorCallbackExists = depBlock.expr.arguments.length === 4 || (!depBlock.chunkName && depBlock.expr.arguments.length === 3); + const errorCallbackExists = + depBlock.expr.arguments.length === 4 || + (!depBlock.chunkName && depBlock.expr.arguments.length === 3); const startBlock = `${promise}.then((`; const middleBlock = ").bind(null, __webpack_require__)).catch("; const endBlock = `).bind(null, __webpack_require__)).catch(${runtime.onError()})`; - source.replace(depBlock.expr.range[0], depBlock.expr.arguments[1].range[0] - 1, startBlock); - if(errorCallbackExists) { - source.replace(depBlock.expr.arguments[1].range[1], depBlock.expr.arguments[2].range[0] - 1, middleBlock); - source.replace(depBlock.expr.arguments[2].range[1], depBlock.expr.range[1] - 1, ")"); + source.replace( + depBlock.expr.range[0], + depBlock.expr.arguments[1].range[0] - 1, + startBlock + ); + if (errorCallbackExists) { + source.replace( + depBlock.expr.arguments[1].range[1], + depBlock.expr.arguments[2].range[0] - 1, + middleBlock + ); + source.replace( + depBlock.expr.arguments[2].range[1], + depBlock.expr.range[1] - 1, + ")" + ); } else { - source.replace(depBlock.expr.arguments[1].range[1], depBlock.expr.range[1] - 1, endBlock); + source.replace( + depBlock.expr.arguments[1].range[1], + depBlock.expr.range[1] - 1, + endBlock + ); } } }; diff --git a/lib/dependencies/RequireEnsurePlugin.js b/lib/dependencies/RequireEnsurePlugin.js index 33316b3d6..e508ec4fc 100644 --- a/lib/dependencies/RequireEnsurePlugin.js +++ b/lib/dependencies/RequireEnsurePlugin.js @@ -14,29 +14,61 @@ const RequireEnsureDependenciesBlockParserPlugin = require("./RequireEnsureDepen const ParserHelpers = require("../ParserHelpers"); class RequireEnsurePlugin { - apply(compiler) { - compiler.hooks.compilation.tap("RequireEnsurePlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(RequireEnsureItemDependency, normalModuleFactory); - compilation.dependencyTemplates.set(RequireEnsureItemDependency, new RequireEnsureItemDependency.Template()); + compiler.hooks.compilation.tap( + "RequireEnsurePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + RequireEnsureItemDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + RequireEnsureItemDependency, + new RequireEnsureItemDependency.Template() + ); - compilation.dependencyFactories.set(RequireEnsureDependency, new NullFactory()); - compilation.dependencyTemplates.set(RequireEnsureDependency, new RequireEnsureDependency.Template()); + compilation.dependencyFactories.set( + RequireEnsureDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + RequireEnsureDependency, + new RequireEnsureDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.requireEnsure !== "undefined" && !parserOptions.requireEnsure) - return; + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.requireEnsure !== "undefined" && + !parserOptions.requireEnsure + ) + return; - new RequireEnsureDependenciesBlockParserPlugin().apply(parser); - parser.hooks.evaluateTypeof.for("require.ensure").tap("RequireEnsurePlugin", ParserHelpers.evaluateToString("function")); - parser.hooks.typeof.for("require.ensure").tap("RequireEnsurePlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("function"))); - }; + new RequireEnsureDependenciesBlockParserPlugin().apply(parser); + parser.hooks.evaluateTypeof + .for("require.ensure") + .tap( + "RequireEnsurePlugin", + ParserHelpers.evaluateToString("function") + ); + parser.hooks.typeof + .for("require.ensure") + .tap( + "RequireEnsurePlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("RequireEnsurePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("RequireEnsurePlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireEnsurePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireEnsurePlugin", handler); + } + ); } } module.exports = RequireEnsurePlugin; diff --git a/lib/dependencies/RequireHeaderDependency.js b/lib/dependencies/RequireHeaderDependency.js index 624bf9ce7..6dddd0623 100644 --- a/lib/dependencies/RequireHeaderDependency.js +++ b/lib/dependencies/RequireHeaderDependency.js @@ -8,7 +8,7 @@ const NullDependency = require("./NullDependency"); class RequireHeaderDependency extends NullDependency { constructor(range) { super(); - if(!Array.isArray(range)) throw new Error("range must be valid"); + if (!Array.isArray(range)) throw new Error("range must be valid"); this.range = range; } } diff --git a/lib/dependencies/RequireIncludeDependency.js b/lib/dependencies/RequireIncludeDependency.js index e429f002d..8181f7f00 100644 --- a/lib/dependencies/RequireIncludeDependency.js +++ b/lib/dependencies/RequireIncludeDependency.js @@ -14,7 +14,7 @@ class RequireIncludeDependency extends ModuleDependency { } getReference() { - if(!this.module) return null; + if (!this.module) return null; return { module: this.module, importedNames: [] // This doesn't use any export @@ -28,7 +28,11 @@ class RequireIncludeDependency extends ModuleDependency { RequireIncludeDependency.Template = class RequireIncludeDependencyTemplate { apply(dep, source, runtime) { - const comment = runtime.outputOptions.pathinfo ? Template.toComment(`require.include ${runtime.requestShortener.shorten(dep.request)}`) : ""; + const comment = runtime.outputOptions.pathinfo + ? Template.toComment( + `require.include ${runtime.requestShortener.shorten(dep.request)}` + ) + : ""; source.replace(dep.range[0], dep.range[1] - 1, `undefined${comment}`); } }; diff --git a/lib/dependencies/RequireIncludeDependencyParserPlugin.js b/lib/dependencies/RequireIncludeDependencyParserPlugin.js index 1d278feaf..117e20451 100644 --- a/lib/dependencies/RequireIncludeDependencyParserPlugin.js +++ b/lib/dependencies/RequireIncludeDependencyParserPlugin.js @@ -8,14 +8,16 @@ const RequireIncludeDependency = require("./RequireIncludeDependency"); module.exports = class RequireIncludeDependencyParserPlugin { apply(parser) { - parser.hooks.call.for("require.include").tap("RequireIncludeDependencyParserPlugin", expr => { - if(expr.arguments.length !== 1) return; - const param = parser.evaluateExpression(expr.arguments[0]); - if(!param.isString()) return; - const dep = new RequireIncludeDependency(param.string, expr.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - }); + parser.hooks.call + .for("require.include") + .tap("RequireIncludeDependencyParserPlugin", expr => { + if (expr.arguments.length !== 1) return; + const param = parser.evaluateExpression(expr.arguments[0]); + if (!param.isString()) return; + const dep = new RequireIncludeDependency(param.string, expr.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + }); } }; diff --git a/lib/dependencies/RequireIncludePlugin.js b/lib/dependencies/RequireIncludePlugin.js index 95b1bab04..e5811a07e 100644 --- a/lib/dependencies/RequireIncludePlugin.js +++ b/lib/dependencies/RequireIncludePlugin.js @@ -11,24 +11,51 @@ const ParserHelpers = require("../ParserHelpers"); class RequireIncludePlugin { apply(compiler) { - compiler.hooks.compilation.tap("RequireIncludePlugin", (compilation, { - normalModuleFactory - }) => { - compilation.dependencyFactories.set(RequireIncludeDependency, normalModuleFactory); - compilation.dependencyTemplates.set(RequireIncludeDependency, new RequireIncludeDependency.Template()); + compiler.hooks.compilation.tap( + "RequireIncludePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + RequireIncludeDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + RequireIncludeDependency, + new RequireIncludeDependency.Template() + ); - const handler = (parser, parserOptions) => { - if(typeof parserOptions.requireInclude !== "undefined" && !parserOptions.requireInclude) - return; + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.requireInclude !== "undefined" && + !parserOptions.requireInclude + ) + return; - new RequireIncludeDependencyParserPlugin().apply(parser); - parser.hooks.evaluateTypeof.for("require.include").tap("RequireIncludePlugin", ParserHelpers.evaluateToString("function")); - parser.hooks.typeof.for("require.include").tap("RequireIncludePlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("function"))); - }; + new RequireIncludeDependencyParserPlugin().apply(parser); + parser.hooks.evaluateTypeof + .for("require.include") + .tap( + "RequireIncludePlugin", + ParserHelpers.evaluateToString("function") + ); + parser.hooks.typeof + .for("require.include") + .tap( + "RequireIncludePlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("RequireIncludePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("RequireIncludePlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireIncludePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireIncludePlugin", handler); + } + ); } } module.exports = RequireIncludePlugin; diff --git a/lib/dependencies/RequireResolveContextDependency.js b/lib/dependencies/RequireResolveContextDependency.js index a309c74f3..cc40451c9 100644 --- a/lib/dependencies/RequireResolveContextDependency.js +++ b/lib/dependencies/RequireResolveContextDependency.js @@ -16,7 +16,6 @@ class RequireResolveContextDependency extends ContextDependency { get type() { return "amd require context"; } - } RequireResolveContextDependency.Template = ContextDependencyTemplateAsId; diff --git a/lib/dependencies/RequireResolveDependencyParserPlugin.js b/lib/dependencies/RequireResolveDependencyParserPlugin.js index 7baab07f2..4c51ddf6a 100644 --- a/lib/dependencies/RequireResolveDependencyParserPlugin.js +++ b/lib/dependencies/RequireResolveDependencyParserPlugin.js @@ -18,12 +18,12 @@ class RequireResolveDependencyParserPlugin { const options = this.options; const process = (expr, weak) => { - if(expr.arguments.length !== 1) return; + if (expr.arguments.length !== 1) return; const param = parser.evaluateExpression(expr.arguments[0]); - if(param.isConditional()) { - for(const option of param.options) { + if (param.isConditional()) { + for (const option of param.options) { const result = processItem(expr, option, weak); - if(result === undefined) { + if (result === undefined) { processContext(expr, option, weak); } } @@ -33,7 +33,7 @@ class RequireResolveDependencyParserPlugin { return true; } else { const result = processItem(expr, param, weak); - if(result === undefined) { + if (result === undefined) { processContext(expr, param, weak); } const dep = new RequireResolveHeaderDependency(expr.callee.range); @@ -43,7 +43,7 @@ class RequireResolveDependencyParserPlugin { } }; const processItem = (expr, param, weak) => { - if(param.isString()) { + if (param.isString()) { const dep = new RequireResolveDependency(param.string, param.range); dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; @@ -53,22 +53,33 @@ class RequireResolveDependencyParserPlugin { } }; const processContext = (expr, param, weak) => { - const dep = ContextDependencyHelpers.create(RequireResolveContextDependency, param.range, param, expr, options, { - mode: weak ? "weak" : "sync" - }); - if(!dep) return; + const dep = ContextDependencyHelpers.create( + RequireResolveContextDependency, + param.range, + param, + expr, + options, + { + mode: weak ? "weak" : "sync" + } + ); + if (!dep) return; dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); return true; }; - parser.hooks.call.for("require.resolve").tap("RequireResolveDependencyParserPlugin", (expr) => { - return process(expr, false); - }); - parser.hooks.call.for("require.resolveWeak").tap("RequireResolveDependencyParserPlugin", (expr) => { - return process(expr, true); - }); + parser.hooks.call + .for("require.resolve") + .tap("RequireResolveDependencyParserPlugin", expr => { + return process(expr, false); + }); + parser.hooks.call + .for("require.resolveWeak") + .tap("RequireResolveDependencyParserPlugin", expr => { + return process(expr, true); + }); } } module.exports = RequireResolveDependencyParserPlugin; diff --git a/lib/dependencies/RequireResolveHeaderDependency.js b/lib/dependencies/RequireResolveHeaderDependency.js index aee5a03b9..05fe86d69 100644 --- a/lib/dependencies/RequireResolveHeaderDependency.js +++ b/lib/dependencies/RequireResolveHeaderDependency.js @@ -8,7 +8,7 @@ const NullDependency = require("./NullDependency"); class RequireResolveHeaderDependency extends NullDependency { constructor(range) { super(); - if(!Array.isArray(range)) throw new Error("range must be valid"); + if (!Array.isArray(range)) throw new Error("range must be valid"); this.range = range; } } diff --git a/lib/dependencies/SystemPlugin.js b/lib/dependencies/SystemPlugin.js index dd5c61a7e..f20af45c6 100644 --- a/lib/dependencies/SystemPlugin.js +++ b/lib/dependencies/SystemPlugin.js @@ -13,49 +13,96 @@ class SystemPlugin { } apply(compiler) { - compiler.hooks.compilation.tap("SystemPlugin", (compilation, { - normalModuleFactory - }) => { - const handler = (parser, parserOptions) => { - if(typeof parserOptions.system !== "undefined" && !parserOptions.system) - return; + compiler.hooks.compilation.tap( + "SystemPlugin", + (compilation, { normalModuleFactory }) => { + const handler = (parser, parserOptions) => { + if ( + typeof parserOptions.system !== "undefined" && + !parserOptions.system + ) + return; - const shouldWarn = typeof parserOptions.system === "undefined"; + const shouldWarn = typeof parserOptions.system === "undefined"; - const setNotSupported = name => { - parser.hooks.evaluateTypeof.for(name).tap("SystemPlugin", ParserHelpers.evaluateToString("undefined")); - parser.hooks.expression.for(name).tap("SystemPlugin", - ParserHelpers.expressionIsUnsupported(parser, name + " is not supported by webpack.") - ); + const setNotSupported = name => { + parser.hooks.evaluateTypeof + .for(name) + .tap("SystemPlugin", ParserHelpers.evaluateToString("undefined")); + parser.hooks.expression + .for(name) + .tap( + "SystemPlugin", + ParserHelpers.expressionIsUnsupported( + parser, + name + " is not supported by webpack." + ) + ); + }; + + parser.hooks.typeof + .for("System.import") + .tap( + "SystemPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for("System.import") + .tap("SystemPlugin", ParserHelpers.evaluateToString("function")); + parser.hooks.typeof + .for("System") + .tap( + "SystemPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("object") + ) + ); + parser.hooks.evaluateTypeof + .for("System") + .tap("SystemPlugin", ParserHelpers.evaluateToString("object")); + + setNotSupported("System.set"); + setNotSupported("System.get"); + setNotSupported("System.register"); + + parser.hooks.expression.for("System").tap("SystemPlugin", () => { + const systemPolyfillRequire = ParserHelpers.requireFileAsExpression( + parser.state.module.context, + require.resolve("../../buildin/system.js") + ); + return ParserHelpers.addParsedVariableToModule( + parser, + "System", + systemPolyfillRequire + ); + }); + + parser.hooks.call.for("System.import").tap("SystemPlugin", expr => { + if (shouldWarn) { + parser.state.module.warnings.push( + new SystemImportDeprecationWarning( + parser.state.module, + expr.loc + ) + ); + } + + return parser.hooks.importCall.call(expr); + }); }; - parser.hooks.typeof.for("System.import").tap("SystemPlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("function"))); - parser.hooks.evaluateTypeof.for("System.import").tap("SystemPlugin", ParserHelpers.evaluateToString("function")); - parser.hooks.typeof.for("System").tap("SystemPlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("object"))); - parser.hooks.evaluateTypeof.for("System").tap("SystemPlugin", ParserHelpers.evaluateToString("object")); - - setNotSupported("System.set"); - setNotSupported("System.get"); - setNotSupported("System.register"); - - parser.hooks.expression.for("System").tap("SystemPlugin", () => { - const systemPolyfillRequire = ParserHelpers.requireFileAsExpression( - parser.state.module.context, require.resolve("../../buildin/system.js")); - return ParserHelpers.addParsedVariableToModule(parser, "System", systemPolyfillRequire); - }); - - parser.hooks.call.for("System.import").tap("SystemPlugin", expr => { - if(shouldWarn) { - parser.state.module.warnings.push(new SystemImportDeprecationWarning(parser.state.module, expr.loc)); - } - - return parser.hooks.importCall.call(expr); - }); - }; - - normalModuleFactory.hooks.parser.for("javascript/auto").tap("SystemPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("SystemPlugin", handler); - }); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("SystemPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("SystemPlugin", handler); + } + ); } } @@ -64,7 +111,8 @@ class SystemImportDeprecationWarning extends WebpackError { super(); this.name = "SystemImportDeprecationWarning"; - this.message = "System.import() is deprecated and will be removed soon. Use import() instead.\n" + + this.message = + "System.import() is deprecated and will be removed soon. Use import() instead.\n" + "For more info visit https://webpack.js.org/guides/code-splitting/"; this.origin = this.module = module; diff --git a/lib/dependencies/UnsupportedDependency.js b/lib/dependencies/UnsupportedDependency.js index be1fd7085..614af783e 100644 --- a/lib/dependencies/UnsupportedDependency.js +++ b/lib/dependencies/UnsupportedDependency.js @@ -16,7 +16,11 @@ class UnsupportedDependency extends NullDependency { UnsupportedDependency.Template = class UnsupportedDependencyTemplate { apply(dep, source, runtime) { - source.replace(dep.range[0], dep.range[1], webpackMissingModule(dep.request)); + source.replace( + dep.range[0], + dep.range[1], + webpackMissingModule(dep.request) + ); } }; diff --git a/lib/dependencies/WebAssemblyImportDependency.js b/lib/dependencies/WebAssemblyImportDependency.js index eba79151b..dc773c8f1 100644 --- a/lib/dependencies/WebAssemblyImportDependency.js +++ b/lib/dependencies/WebAssemblyImportDependency.js @@ -12,7 +12,7 @@ class WebAssemblyImportDependency extends ModuleDependency { } getReference() { - if(!this.module) return null; + if (!this.module) return null; return { module: this.module, importedNames: [this.name] diff --git a/lib/dependencies/WebpackMissingModule.js b/lib/dependencies/WebpackMissingModule.js index ed627e845..f0b58fd64 100644 --- a/lib/dependencies/WebpackMissingModule.js +++ b/lib/dependencies/WebpackMissingModule.js @@ -3,16 +3,20 @@ Author Tobias Koppers @sokra */ "use strict"; -const toErrorCode = err => `var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND';`; +const toErrorCode = err => + `var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND';`; -exports.module = request => `!(function webpackMissingModule() { ${exports.moduleCode(request)} }())`; +exports.module = request => + `!(function webpackMissingModule() { ${exports.moduleCode(request)} }())`; -exports.promise = (request) => { +exports.promise = request => { const errorCode = toErrorCode(`Cannot find module "${request}"`); - return `Promise.reject(function webpackMissingModule() { ${errorCode} return e; }())`; + return `Promise.reject(function webpackMissingModule() { ${ + errorCode + } return e; }())`; }; -exports.moduleCode = (request) => { +exports.moduleCode = request => { const errorCode = toErrorCode(`Cannot find module "${request}"`); return `${errorCode} throw e;`; }; diff --git a/lib/dependencies/getFunctionExpression.js b/lib/dependencies/getFunctionExpression.js index abef04030..33db4260c 100644 --- a/lib/dependencies/getFunctionExpression.js +++ b/lib/dependencies/getFunctionExpression.js @@ -4,7 +4,10 @@ */ module.exports = expr => { // - if(expr.type === "FunctionExpression" || expr.type === "ArrowFunctionExpression") { + if ( + expr.type === "FunctionExpression" || + expr.type === "ArrowFunctionExpression" + ) { return { fn: expr, expressions: [], @@ -13,19 +16,22 @@ module.exports = expr => { } // .bind() - if(expr.type === "CallExpression" && + if ( + expr.type === "CallExpression" && expr.callee.type === "MemberExpression" && expr.callee.object.type === "FunctionExpression" && expr.callee.property.type === "Identifier" && expr.callee.property.name === "bind" && - expr.arguments.length === 1) { + expr.arguments.length === 1 + ) { return { fn: expr.callee.object, expressions: [expr.arguments[0]] }; } // (function(_this) {return })(this) (Coffeescript) - if(expr.type === "CallExpression" && + if ( + expr.type === "CallExpression" && expr.callee.type === "FunctionExpression" && expr.callee.body.type === "BlockStatement" && expr.arguments.length === 1 && @@ -34,7 +40,8 @@ module.exports = expr => { expr.callee.body.body.length === 1 && expr.callee.body.body[0].type === "ReturnStatement" && expr.callee.body.body[0].argument && - expr.callee.body.body[0].argument.type === "FunctionExpression") { + expr.callee.body.body[0].argument.type === "FunctionExpression" + ) { return { fn: expr.callee.body.body[0].argument, expressions: [], diff --git a/lib/formatLocation.js b/lib/formatLocation.js index 82f37f3b8..214838beb 100644 --- a/lib/formatLocation.js +++ b/lib/formatLocation.js @@ -5,46 +5,45 @@ "use strict"; -const formatPosition = (pos) => { - if(pos === null) - return ""; +const formatPosition = pos => { + if (pos === null) return ""; const typeOfPos = typeof pos; - switch(typeOfPos) { + switch (typeOfPos) { case "string": return pos; case "number": return `${pos}`; case "object": - if(typeof pos.line === "number" && typeof pos.column === "number") + if (typeof pos.line === "number" && typeof pos.column === "number") return `${pos.line}:${pos.column}`; - else if(typeof pos.line === "number") - return `${pos.line}:?`; - else if(typeof pos.index === "number") - return `+${pos.index}`; - else - return ""; + else if (typeof pos.line === "number") return `${pos.line}:?`; + else if (typeof pos.index === "number") return `+${pos.index}`; + else return ""; default: return ""; } }; -const formatLocation = (loc) => { - if(loc === null) - return ""; +const formatLocation = loc => { + if (loc === null) return ""; const typeOfLoc = typeof loc; - switch(typeOfLoc) { + switch (typeOfLoc) { case "string": return loc; case "number": return `${loc}`; case "object": - if(loc.start && loc.end) { - if(typeof loc.start.line === "number" && typeof loc.end.line === "number" && typeof loc.end.column === "number" && loc.start.line === loc.end.line) + if (loc.start && loc.end) { + if ( + typeof loc.start.line === "number" && + typeof loc.end.line === "number" && + typeof loc.end.column === "number" && + loc.start.line === loc.end.line + ) return `${formatPosition(loc.start)}-${loc.end.column}`; return `${formatPosition(loc.start)}-${formatPosition(loc.end)}`; } - if(loc.start) - return formatPosition(loc.start); + if (loc.start) return formatPosition(loc.start); return formatPosition(loc); default: return ""; diff --git a/lib/node/NodeChunkTemplatePlugin.js b/lib/node/NodeChunkTemplatePlugin.js index 327eb5aae..25e2eedd0 100644 --- a/lib/node/NodeChunkTemplatePlugin.js +++ b/lib/node/NodeChunkTemplatePlugin.js @@ -8,15 +8,19 @@ const ConcatSource = require("webpack-sources").ConcatSource; class NodeChunkTemplatePlugin { - apply(chunkTemplate) { - chunkTemplate.hooks.render.tap("NodeChunkTemplatePlugin", (modules, chunk) => { - const source = new ConcatSource(); - source.add(`exports.ids = ${JSON.stringify(chunk.ids)};\nexports.modules = `); - source.add(modules); - source.add(";"); - return source; - }); + chunkTemplate.hooks.render.tap( + "NodeChunkTemplatePlugin", + (modules, chunk) => { + const source = new ConcatSource(); + source.add( + `exports.ids = ${JSON.stringify(chunk.ids)};\nexports.modules = ` + ); + source.add(modules); + source.add(";"); + return source; + } + ); chunkTemplate.hooks.hash.tap("NodeChunkTemplatePlugin", hash => { hash.update("node"); hash.update("3"); diff --git a/lib/node/NodeEnvironmentPlugin.js b/lib/node/NodeEnvironmentPlugin.js index 1f263eddf..3f76bffa5 100644 --- a/lib/node/NodeEnvironmentPlugin.js +++ b/lib/node/NodeEnvironmentPlugin.js @@ -11,13 +11,17 @@ const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSyste class NodeEnvironmentPlugin { apply(compiler) { - compiler.inputFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 60000); + compiler.inputFileSystem = new CachedInputFileSystem( + new NodeJsInputFileSystem(), + 60000 + ); const inputFileSystem = compiler.inputFileSystem; compiler.outputFileSystem = new NodeOutputFileSystem(); - compiler.watchFileSystem = new NodeWatchFileSystem(compiler.inputFileSystem); - compiler.hooks.beforeRun.tap("NodeEnvironmentPlugin", (compiler) => { - if(compiler.inputFileSystem === inputFileSystem) - inputFileSystem.purge(); + compiler.watchFileSystem = new NodeWatchFileSystem( + compiler.inputFileSystem + ); + compiler.hooks.beforeRun.tap("NodeEnvironmentPlugin", compiler => { + if (compiler.inputFileSystem === inputFileSystem) inputFileSystem.purge(); }); } } diff --git a/lib/node/NodeHotUpdateChunkTemplatePlugin.js b/lib/node/NodeHotUpdateChunkTemplatePlugin.js index 4d9ac7648..6a01d5529 100644 --- a/lib/node/NodeHotUpdateChunkTemplatePlugin.js +++ b/lib/node/NodeHotUpdateChunkTemplatePlugin.js @@ -7,21 +7,30 @@ const ConcatSource = require("webpack-sources").ConcatSource; class NodeHotUpdateChunkTemplatePlugin { - apply(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.hooks.render.tap("NodeHotUpdateChunkTemplatePlugin", (modulesSource, modules, removedModules, hash, id) => { - const source = new ConcatSource(); - source.add("exports.id = " + JSON.stringify(id) + ";\nexports.modules = "); - source.add(modulesSource); - source.add(";"); - return source; - }); - hotUpdateChunkTemplate.hooks.hash.tap("NodeHotUpdateChunkTemplatePlugin", hash => { - hash.update("NodeHotUpdateChunkTemplatePlugin"); - hash.update("3"); - hash.update(hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + ""); - hash.update(hotUpdateChunkTemplate.outputOptions.library + ""); - }); + hotUpdateChunkTemplate.hooks.render.tap( + "NodeHotUpdateChunkTemplatePlugin", + (modulesSource, modules, removedModules, hash, id) => { + const source = new ConcatSource(); + source.add( + "exports.id = " + JSON.stringify(id) + ";\nexports.modules = " + ); + source.add(modulesSource); + source.add(";"); + return source; + } + ); + hotUpdateChunkTemplate.hooks.hash.tap( + "NodeHotUpdateChunkTemplatePlugin", + hash => { + hash.update("NodeHotUpdateChunkTemplatePlugin"); + hash.update("3"); + hash.update( + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + "" + ); + hash.update(hotUpdateChunkTemplate.outputOptions.library + ""); + } + ); } } module.exports = NodeHotUpdateChunkTemplatePlugin; diff --git a/lib/node/NodeMainTemplate.runtime.js b/lib/node/NodeMainTemplate.runtime.js index 8460325d8..b8ab8c4c7 100644 --- a/lib/node/NodeMainTemplate.runtime.js +++ b/lib/node/NodeMainTemplate.runtime.js @@ -4,21 +4,24 @@ */ /*global installedChunks $hotChunkFilename$ hotAddUpdateChunk $hotMainFilename$ */ module.exports = function() { - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + // eslint-disable-line no-unused-vars var chunk = require("./" + $hotChunkFilename$); hotAddUpdateChunk(chunk.id, chunk.modules); } - function hotDownloadManifest() { // eslint-disable-line no-unused-vars + function hotDownloadManifest() { + // eslint-disable-line no-unused-vars try { var update = require("./" + $hotMainFilename$); - } catch(e) { + } catch (e) { return Promise.resolve(); } return Promise.resolve(update); } - function hotDisposeChunk(chunkId) { //eslint-disable-line no-unused-vars + function hotDisposeChunk(chunkId) { + //eslint-disable-line no-unused-vars delete installedChunks[chunkId]; } }; diff --git a/lib/node/NodeMainTemplateAsync.runtime.js b/lib/node/NodeMainTemplateAsync.runtime.js index 2d98d9ea7..2103e0c57 100644 --- a/lib/node/NodeMainTemplateAsync.runtime.js +++ b/lib/node/NodeMainTemplateAsync.runtime.js @@ -4,29 +4,32 @@ */ /*global installedChunks $hotChunkFilename$ $require$ hotAddUpdateChunk $hotMainFilename$ */ module.exports = function() { - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + // eslint-disable-line no-unused-vars var filename = require("path").join(__dirname, $hotChunkFilename$); require("fs").readFile(filename, "utf-8", function(err, content) { - if(err) { - if($require$.onError) - return $require$.oe(err); - else - throw err; + if (err) { + if ($require$.onError) return $require$.oe(err); + else throw err; } var chunk = {}; - require("vm").runInThisContext("(function(exports) {" + content + "\n})", filename)(chunk); + require("vm").runInThisContext( + "(function(exports) {" + content + "\n})", + filename + )(chunk); hotAddUpdateChunk(chunk.id, chunk.modules); }); } - function hotDownloadManifest() { // eslint-disable-line no-unused-vars + function hotDownloadManifest() { + // eslint-disable-line no-unused-vars var filename = require("path").join(__dirname, $hotMainFilename$); return new Promise(function(resolve, reject) { require("fs").readFile(filename, "utf-8", function(err, content) { - if(err) return resolve(); + if (err) return resolve(); try { var update = JSON.parse(content); - } catch(e) { + } catch (e) { return reject(e); } resolve(update); @@ -34,7 +37,8 @@ module.exports = function() { }); } - function hotDisposeChunk(chunkId) { //eslint-disable-line no-unused-vars + function hotDisposeChunk(chunkId) { + //eslint-disable-line no-unused-vars delete installedChunks[chunkId]; } }; diff --git a/lib/node/NodeMainTemplatePlugin.js b/lib/node/NodeMainTemplatePlugin.js index 2298a5f04..c4f577ea5 100644 --- a/lib/node/NodeMainTemplatePlugin.js +++ b/lib/node/NodeMainTemplatePlugin.js @@ -13,183 +13,256 @@ module.exports = class NodeMainTemplatePlugin { apply(mainTemplate) { const needChunkOnDemandLoadingCode = chunk => { - for(const chunkGroup of chunk.groupsIterable) { - if(chunkGroup.getNumberOfChildren() > 0) return true; + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.getNumberOfChildren() > 0) return true; } return false; }; const asyncChunkLoading = this.asyncChunkLoading; - mainTemplate.hooks.localVars.tap("NodeMainTemplatePlugin", (source, chunk) => { - if(needChunkOnDemandLoadingCode(chunk)) { - return Template.asString([ - source, - "", - "// object to store loaded chunks", - "// \"0\" means \"already loaded\"", - "var installedChunks = {", - Template.indent(chunk.ids.map((id) => `${id}: 0`).join(",\n")), - "};" - ]); + mainTemplate.hooks.localVars.tap( + "NodeMainTemplatePlugin", + (source, chunk) => { + if (needChunkOnDemandLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// object to store loaded chunks", + '// "0" means "already loaded"', + "var installedChunks = {", + Template.indent(chunk.ids.map(id => `${id}: 0`).join(",\n")), + "};" + ]); + } + return source; } - return source; - }); - mainTemplate.hooks.requireExtensions.tap("NodeMainTemplatePlugin", (source, chunk) => { - if(needChunkOnDemandLoadingCode(chunk)) { - return Template.asString([ - source, - "", - "// uncatched error handler for webpack runtime", - `${mainTemplate.requireFn}.oe = function(err) {`, - Template.indent([ - "process.nextTick(function() {", - Template.indent("throw err; // catch this error by using import().catch()"), - "});" - ]), - "};" - ]); - } - return source; - }); - mainTemplate.hooks.requireEnsure.tap("NodeMainTemplatePlugin", (source, chunk, hash) => { - const chunkFilename = mainTemplate.outputOptions.chunkFilename; - const chunkMaps = chunk.getChunkMaps(); - const insertMoreModules = [ - "var moreModules = chunk.modules, chunkIds = chunk.ids;", - "for(var moduleId in moreModules) {", - Template.indent(mainTemplate.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")), - "}" - ]; - if(asyncChunkLoading) { - return Template.asString([ - source, - "", - "// ReadFile + VM.run chunk loading for javascript", - "", - "var installedChunkData = installedChunks[chunkId];", - "if(installedChunkData !== 0) { // 0 means \"already installed\".", - Template.indent([ - "// array of [resolve, reject, promise] means \"currently loading\"", - "if(installedChunkData) {", + ); + mainTemplate.hooks.requireExtensions.tap( + "NodeMainTemplatePlugin", + (source, chunk) => { + if (needChunkOnDemandLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// uncatched error handler for webpack runtime", + `${mainTemplate.requireFn}.oe = function(err) {`, Template.indent([ - "promises.push(installedChunkData[2]);" + "process.nextTick(function() {", + Template.indent( + "throw err; // catch this error by using import().catch()" + ), + "});" ]), - "} else {", + "};" + ]); + } + return source; + } + ); + mainTemplate.hooks.requireEnsure.tap( + "NodeMainTemplatePlugin", + (source, chunk, hash) => { + const chunkFilename = mainTemplate.outputOptions.chunkFilename; + const chunkMaps = chunk.getChunkMaps(); + const insertMoreModules = [ + "var moreModules = chunk.modules, chunkIds = chunk.ids;", + "for(var moduleId in moreModules) {", + Template.indent( + mainTemplate.renderAddModule( + hash, + chunk, + "moduleId", + "moreModules[moduleId]" + ) + ), + "}" + ]; + if (asyncChunkLoading) { + return Template.asString([ + source, + "", + "// ReadFile + VM.run chunk loading for javascript", + "", + "var installedChunkData = installedChunks[chunkId];", + 'if(installedChunkData !== 0) { // 0 means "already installed".', Template.indent([ - "// load the chunk and return promise to it", - "var promise = new Promise(function(resolve, reject) {", + '// array of [resolve, reject, promise] means "currently loading"', + "if(installedChunkData) {", + Template.indent(["promises.push(installedChunkData[2]);"]), + "} else {", Template.indent([ - "installedChunkData = installedChunks[chunkId] = [resolve, reject];", - "var filename = __dirname + " + mainTemplate.getAssetPath(JSON.stringify(`/${chunkFilename}`), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength: (length) => { - const shortChunkHashMap = {}; - for(const chunkId of Object.keys(chunkMaps.hash)) { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); - } - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }) + ";", - "require('fs').readFile(filename, 'utf-8', function(err, content) {", + "// load the chunk and return promise to it", + "var promise = new Promise(function(resolve, reject) {", Template.indent([ - "if(err) return reject(err);", - "var chunk = {};", - "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + - "(chunk, require, require('path').dirname(filename), filename);" - ].concat(insertMoreModules).concat([ - "var callbacks = [];", - "for(var i = 0; i < chunkIds.length; i++) {", - Template.indent([ - "if(installedChunks[chunkIds[i]])", - Template.indent([ - "callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);" - ]), - "installedChunks[chunkIds[i]] = 0;" - ]), - "}", - "for(i = 0; i < callbacks.length; i++)", - Template.indent("callbacks[i]();") - ])), - "});" + "installedChunkData = installedChunks[chunkId] = [resolve, reject];", + "var filename = __dirname + " + + mainTemplate.getAssetPath( + JSON.stringify(`/${chunkFilename}`), + { + hash: `" + ${mainTemplate.renderCurrentHashCode( + hash + )} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode( + hash, + length + )} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify( + chunkMaps.hash + )}[chunkId] + "`, + hashWithLength: length => { + const shortChunkHashMap = {}; + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") + shortChunkHashMap[chunkId] = chunkMaps.hash[ + chunkId + ].substr(0, length); + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[chunkId] + "`; + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + } + } + ) + + ";", + "require('fs').readFile(filename, 'utf-8', function(err, content) {", + Template.indent( + [ + "if(err) return reject(err);", + "var chunk = {};", + "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + + "(chunk, require, require('path').dirname(filename), filename);" + ] + .concat(insertMoreModules) + .concat([ + "var callbacks = [];", + "for(var i = 0; i < chunkIds.length; i++) {", + Template.indent([ + "if(installedChunks[chunkIds[i]])", + Template.indent([ + "callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);" + ]), + "installedChunks[chunkIds[i]] = 0;" + ]), + "}", + "for(i = 0; i < callbacks.length; i++)", + Template.indent("callbacks[i]();") + ]) + ), + "});" + ]), + "});", + "promises.push(installedChunkData[2] = promise);" ]), - "});", - "promises.push(installedChunkData[2] = promise);" + "}" ]), "}" - ]), - "}" - ]); - } else { - const request = mainTemplate.getAssetPath(JSON.stringify(`./${chunkFilename}`), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength: (length) => { - const shortChunkHashMap = {}; - for(const chunkId of Object.keys(chunkMaps.hash)) { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); + ]); + } else { + const request = mainTemplate.getAssetPath( + JSON.stringify(`./${chunkFilename}`), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength: length => { + const shortChunkHashMap = {}; + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") + shortChunkHashMap[chunkId] = chunkMaps.hash[ + chunkId + ].substr(0, length); + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[chunkId] + "`; + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` } - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }); - return Template.asString([ - source, - "", - "// require() chunk loading for javascript", - "", - "// \"0\" is the signal for \"already loaded\"", - "if(installedChunks[chunkId] !== 0) {", - Template.indent([ - `var chunk = require(${request});` - ].concat(insertMoreModules).concat([ - "for(var i = 0; i < chunkIds.length; i++)", - Template.indent("installedChunks[chunkIds[i]] = 0;") - ])), - "}", - ]); - } - }); - mainTemplate.hooks.hotBootstrap.tap("NodeMainTemplatePlugin", (source, chunk, hash) => { - const hotUpdateChunkFilename = mainTemplate.outputOptions.hotUpdateChunkFilename; - const hotUpdateMainFilename = mainTemplate.outputOptions.hotUpdateMainFilename; - const chunkMaps = chunk.getChunkMaps(); - const currentHotUpdateChunkFilename = mainTemplate.getAssetPath(JSON.stringify(hotUpdateChunkFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength: (length) => { - const shortChunkHashMap = {}; - for(const chunkId of Object.keys(chunkMaps.hash)) { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); } - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` + ); + return Template.asString([ + source, + "", + "// require() chunk loading for javascript", + "", + '// "0" is the signal for "already loaded"', + "if(installedChunks[chunkId] !== 0) {", + Template.indent( + [`var chunk = require(${request});`] + .concat(insertMoreModules) + .concat([ + "for(var i = 0; i < chunkIds.length; i++)", + Template.indent("installedChunks[chunkIds[i]] = 0;") + ]) + ), + "}" + ]); } - }); - const currentHotUpdateMainFilename = mainTemplate.getAssetPath(JSON.stringify(hotUpdateMainFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` - }); - return Template.getFunctionContent(asyncChunkLoading ? require("./NodeMainTemplateAsync.runtime.js") : require("./NodeMainTemplate.runtime.js")) - .replace(/\$require\$/g, mainTemplate.requireFn) - .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) - .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename); - }); + } + ); + mainTemplate.hooks.hotBootstrap.tap( + "NodeMainTemplatePlugin", + (source, chunk, hash) => { + const hotUpdateChunkFilename = + mainTemplate.outputOptions.hotUpdateChunkFilename; + const hotUpdateMainFilename = + mainTemplate.outputOptions.hotUpdateMainFilename; + const chunkMaps = chunk.getChunkMaps(); + const currentHotUpdateChunkFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateChunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength: length => { + const shortChunkHashMap = {}; + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") + shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr( + 0, + length + ); + } + return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + } + } + ); + const currentHotUpdateMainFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateMainFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` + } + ); + return Template.getFunctionContent( + asyncChunkLoading + ? require("./NodeMainTemplateAsync.runtime.js") + : require("./NodeMainTemplate.runtime.js") + ) + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) + .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename); + } + ); mainTemplate.hooks.hash.tap("NodeMainTemplatePlugin", hash => { hash.update("node"); hash.update("3"); diff --git a/lib/node/NodeSourcePlugin.js b/lib/node/NodeSourcePlugin.js index caf012cd0..3a49e6377 100644 --- a/lib/node/NodeSourcePlugin.js +++ b/lib/node/NodeSourcePlugin.js @@ -13,16 +13,20 @@ module.exports = class NodeSourcePlugin { } apply(compiler) { const options = this.options; - if(options === false) // allow single kill switch to turn off this plugin + if (options === false) + // allow single kill switch to turn off this plugin return; const getPathToModule = (module, type) => { - if(type === true || (type === undefined && nodeLibsBrowser[module])) { - if(!nodeLibsBrowser[module]) throw new Error(`No browser version for node.js core module ${module} available`); + if (type === true || (type === undefined && nodeLibsBrowser[module])) { + if (!nodeLibsBrowser[module]) + throw new Error( + `No browser version for node.js core module ${module} available` + ); return nodeLibsBrowser[module]; - } else if(type === "mock") { + } else if (type === "mock") { return require.resolve(`node-libs-browser/mock/${module}`); - } else if(type === "empty") { + } else if (type === "empty") { return require.resolve("node-libs-browser/mock/empty"); } else return module; }; @@ -30,61 +34,105 @@ module.exports = class NodeSourcePlugin { const addExpression = (parser, name, module, type, suffix) => { suffix = suffix || ""; parser.hooks.expression.for(name).tap("NodeSourcePlugin", () => { - if(parser.state.module && parser.state.module.resource === getPathToModule(module, type)) return; - const mockModule = ParserHelpers.requireFileAsExpression(parser.state.module.context, getPathToModule(module, type)); - return ParserHelpers.addParsedVariableToModule(parser, name, mockModule + suffix); + if ( + parser.state.module && + parser.state.module.resource === getPathToModule(module, type) + ) + return; + const mockModule = ParserHelpers.requireFileAsExpression( + parser.state.module.context, + getPathToModule(module, type) + ); + return ParserHelpers.addParsedVariableToModule( + parser, + name, + mockModule + suffix + ); }); }; - compiler.hooks.compilation.tap("NodeSourcePlugin", (compilation, { - normalModuleFactory - }) => { - const handler = (parser, parserOptions) => { - if(parserOptions.node === false) - return; + compiler.hooks.compilation.tap( + "NodeSourcePlugin", + (compilation, { normalModuleFactory }) => { + const handler = (parser, parserOptions) => { + if (parserOptions.node === false) return; - let localOptions = options; - if(parserOptions.node) - localOptions = Object.assign({}, localOptions, parserOptions.node); + let localOptions = options; + if (parserOptions.node) + localOptions = Object.assign({}, localOptions, parserOptions.node); - if(localOptions.global) { - parser.hooks.expression.for("global").tap("NodeSourcePlugin", () => { - const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(parser.state.module.context, require.resolve("../../buildin/global.js")); - return ParserHelpers.addParsedVariableToModule(parser, "global", retrieveGlobalModule); - }); - } - if(localOptions.process) { - const processType = localOptions.process; - addExpression(parser, "process", "process", processType); - } - if(localOptions.console) { - const consoleType = localOptions.console; - addExpression(parser, "console", "console", consoleType); - } - const bufferType = localOptions.Buffer; - if(bufferType) { - addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer"); - } - if(localOptions.setImmediate) { - const setImmediateType = localOptions.setImmediate; - addExpression(parser, "setImmediate", "timers", setImmediateType, ".setImmediate"); - addExpression(parser, "clearImmediate", "timers", setImmediateType, ".clearImmediate"); - } - }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("NodeSourcePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("NodeSourcePlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("NodeSourcePlugin", handler); - }); - compiler.hooks.afterResolvers.tap("NodeSourcePlugin", (compiler) => { - for(const lib of Object.keys(nodeLibsBrowser)) { - if(options[lib] !== false) { - compiler.resolverFactory.hooks.resolver.for("normal").tap("NodeSourcePlugin", resolver => { - new AliasPlugin("described-resolve", { - name: lib, - onlyModule: true, - alias: getPathToModule(lib, options[lib]) - }, "resolve").apply(resolver); - }); + if (localOptions.global) { + parser.hooks.expression + .for("global") + .tap("NodeSourcePlugin", () => { + const retrieveGlobalModule = ParserHelpers.requireFileAsExpression( + parser.state.module.context, + require.resolve("../../buildin/global.js") + ); + return ParserHelpers.addParsedVariableToModule( + parser, + "global", + retrieveGlobalModule + ); + }); + } + if (localOptions.process) { + const processType = localOptions.process; + addExpression(parser, "process", "process", processType); + } + if (localOptions.console) { + const consoleType = localOptions.console; + addExpression(parser, "console", "console", consoleType); + } + const bufferType = localOptions.Buffer; + if (bufferType) { + addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer"); + } + if (localOptions.setImmediate) { + const setImmediateType = localOptions.setImmediate; + addExpression( + parser, + "setImmediate", + "timers", + setImmediateType, + ".setImmediate" + ); + addExpression( + parser, + "clearImmediate", + "timers", + setImmediateType, + ".clearImmediate" + ); + } + }; + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("NodeSourcePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("NodeSourcePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("NodeSourcePlugin", handler); + } + ); + compiler.hooks.afterResolvers.tap("NodeSourcePlugin", compiler => { + for (const lib of Object.keys(nodeLibsBrowser)) { + if (options[lib] !== false) { + compiler.resolverFactory.hooks.resolver + .for("normal") + .tap("NodeSourcePlugin", resolver => { + new AliasPlugin( + "described-resolve", + { + name: lib, + onlyModule: true, + alias: getPathToModule(lib, options[lib]) + }, + "resolve" + ).apply(resolver); + }); } } }); diff --git a/lib/node/NodeTargetPlugin.js b/lib/node/NodeTargetPlugin.js index ac2f05a55..ff9cdc882 100644 --- a/lib/node/NodeTargetPlugin.js +++ b/lib/node/NodeTargetPlugin.js @@ -6,7 +6,8 @@ const ExternalsPlugin = require("../ExternalsPlugin"); -const builtins = require("module").builtinModules || Object.keys(process.binding("natives")); +const builtins = + require("module").builtinModules || Object.keys(process.binding("natives")); class NodeTargetPlugin { apply(compiler) { diff --git a/lib/node/NodeTemplatePlugin.js b/lib/node/NodeTemplatePlugin.js index 4422a2c02..cdb1076b9 100644 --- a/lib/node/NodeTemplatePlugin.js +++ b/lib/node/NodeTemplatePlugin.js @@ -16,10 +16,14 @@ class NodeTemplatePlugin { } apply(compiler) { - compiler.hooks.thisCompilation.tap("NodeTemplatePlugin", (compilation) => { - new NodeMainTemplatePlugin(this.asyncChunkLoading).apply(compilation.mainTemplate); + compiler.hooks.thisCompilation.tap("NodeTemplatePlugin", compilation => { + new NodeMainTemplatePlugin(this.asyncChunkLoading).apply( + compilation.mainTemplate + ); new NodeChunkTemplatePlugin().apply(compilation.chunkTemplate); - new NodeHotUpdateChunkTemplatePlugin().apply(compilation.hotUpdateChunkTemplate); + new NodeHotUpdateChunkTemplatePlugin().apply( + compilation.hotUpdateChunkTemplate + ); }); } } diff --git a/lib/node/NodeWatchFileSystem.js b/lib/node/NodeWatchFileSystem.js index f6af06f46..45c3c34e5 100644 --- a/lib/node/NodeWatchFileSystem.js +++ b/lib/node/NodeWatchFileSystem.js @@ -17,66 +17,63 @@ class NodeWatchFileSystem { } watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { - if(!Array.isArray(files)) - throw new Error("Invalid arguments: 'files'"); - if(!Array.isArray(dirs)) - throw new Error("Invalid arguments: 'dirs'"); - if(!Array.isArray(missing)) + if (!Array.isArray(files)) throw new Error("Invalid arguments: 'files'"); + if (!Array.isArray(dirs)) throw new Error("Invalid arguments: 'dirs'"); + if (!Array.isArray(missing)) throw new Error("Invalid arguments: 'missing'"); - if(typeof callback !== "function") + if (typeof callback !== "function") throw new Error("Invalid arguments: 'callback'"); - if(typeof startTime !== "number" && startTime) + if (typeof startTime !== "number" && startTime) throw new Error("Invalid arguments: 'startTime'"); - if(typeof options !== "object") + if (typeof options !== "object") throw new Error("Invalid arguments: 'options'"); - if(typeof callbackUndelayed !== "function" && callbackUndelayed) + if (typeof callbackUndelayed !== "function" && callbackUndelayed) throw new Error("Invalid arguments: 'callbackUndelayed'"); const oldWatcher = this.watcher; this.watcher = new Watchpack(options); - if(callbackUndelayed) - this.watcher.once("change", callbackUndelayed); + if (callbackUndelayed) this.watcher.once("change", callbackUndelayed); this.watcher.once("aggregated", (changes, removals) => { changes = changes.concat(removals); - if(this.inputFileSystem && this.inputFileSystem.purge) { + if (this.inputFileSystem && this.inputFileSystem.purge) { this.inputFileSystem.purge(changes); } const times = objectToMap(this.watcher.getTimes()); - callback(null, + callback( + null, changes.filter(file => files.includes(file)).sort(), changes.filter(file => dirs.includes(file)).sort(), - changes.filter(file => missing.includes(file)).sort(), times, times); + changes.filter(file => missing.includes(file)).sort(), + times, + times + ); }); this.watcher.watch(files.concat(missing), dirs.concat(missing), startTime); - if(oldWatcher) { + if (oldWatcher) { oldWatcher.close(); } return { close: () => { - if(this.watcher) { + if (this.watcher) { this.watcher.close(); this.watcher = null; } }, pause: () => { - if(this.watcher) { + if (this.watcher) { this.watcher.pause(); } }, getFileTimestamps: () => { - if(this.watcher) - return objectToMap(this.watcher.getTimes()); - else - return new Map(); + if (this.watcher) return objectToMap(this.watcher.getTimes()); + else return new Map(); }, getContextTimestamps: () => { - if(this.watcher) - return objectToMap(this.watcher.getTimes()); - else - return new Map(); + if (this.watcher) return objectToMap(this.watcher.getTimes()); + else return new Map(); } }; } diff --git a/lib/node/ReadFileCompileWasmMainTemplatePlugin.js b/lib/node/ReadFileCompileWasmMainTemplatePlugin.js index 85c3ff2a1..1e8a8d60b 100644 --- a/lib/node/ReadFileCompileWasmMainTemplatePlugin.js +++ b/lib/node/ReadFileCompileWasmMainTemplatePlugin.js @@ -7,79 +7,109 @@ const Template = require("../Template"); class ReadFileCompileWasmMainTemplatePlugin { - apply(mainTemplate) { - mainTemplate.hooks.localVars.tap("ReadFileCompileWasmMainTemplatePlugin", (source, chunk) => { - return Template.asString([ - source, - "", - "// object to store loaded and loading wasm modules", - "var installedWasmModules = {};", - ]); - }); - mainTemplate.hooks.requireEnsure.tap("ReadFileCompileWasmMainTemplatePlugin", (source, chunk, hash) => { - const webassemblyModuleFilename = mainTemplate.outputOptions.webassemblyModuleFilename; - const chunkModuleMaps = chunk.getChunkModuleMaps(m => m.type.startsWith("webassembly")); - if(Object.keys(chunkModuleMaps.id).length === 0) return source; - const wasmModuleSrcPath = mainTemplate.getAssetPath(JSON.stringify(webassemblyModuleFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - module: { - id: "\" + wasmModuleId + \"", - hash: `" + ${JSON.stringify(chunkModuleMaps.hash)}[wasmModuleId] + "`, - hashWithLength(length) { - const shortChunkHashMap = Object.create(null); - for(const wasmModuleId of Object.keys(chunkModuleMaps.hash)) { - if(typeof chunkModuleMaps.hash[wasmModuleId] === "string") - shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[wasmModuleId].substr(0, length); - } - return `" + ${JSON.stringify(shortChunkHashMap)}[wasmModuleId] + "`; - } - } - }); - return Template.asString([ - source, - "", - "// ReadFile + compile chunk loading for webassembly", - "", - `var wasmModules = ${JSON.stringify(chunkModuleMaps.id)}[chunkId] || [];`, - "", - "wasmModules.forEach(function(wasmModuleId) {", - Template.indent([ - "var installedWasmModuleData = installedWasmModules[wasmModuleId];", + mainTemplate.hooks.localVars.tap( + "ReadFileCompileWasmMainTemplatePlugin", + (source, chunk) => { + return Template.asString([ + source, "", - "// a Promise means \"currently loading\" or \"already loaded\".", - "promises.push(installedWasmModuleData ||", + "// object to store loaded and loading wasm modules", + "var installedWasmModules = {};" + ]); + } + ); + mainTemplate.hooks.requireEnsure.tap( + "ReadFileCompileWasmMainTemplatePlugin", + (source, chunk, hash) => { + const webassemblyModuleFilename = + mainTemplate.outputOptions.webassemblyModuleFilename; + const chunkModuleMaps = chunk.getChunkModuleMaps(m => + m.type.startsWith("webassembly") + ); + if (Object.keys(chunkModuleMaps.id).length === 0) return source; + const wasmModuleSrcPath = mainTemplate.getAssetPath( + JSON.stringify(webassemblyModuleFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + module: { + id: '" + wasmModuleId + "', + hash: `" + ${JSON.stringify( + chunkModuleMaps.hash + )}[wasmModuleId] + "`, + hashWithLength(length) { + const shortChunkHashMap = Object.create(null); + for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) { + if (typeof chunkModuleMaps.hash[wasmModuleId] === "string") + shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[ + wasmModuleId + ].substr(0, length); + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[wasmModuleId] + "`; + } + } + } + ); + return Template.asString([ + source, + "", + "// ReadFile + compile chunk loading for webassembly", + "", + `var wasmModules = ${JSON.stringify( + chunkModuleMaps.id + )}[chunkId] || [];`, + "", + "wasmModules.forEach(function(wasmModuleId) {", Template.indent([ - "(installedWasmModules[wasmModuleId] = new Promise(function(resolve, reject) {", + "var installedWasmModuleData = installedWasmModules[wasmModuleId];", + "", + '// a Promise means "currently loading" or "already loaded".', + "promises.push(installedWasmModuleData ||", Template.indent([ - `require('fs').readFile(require('path').resolve(__dirname, ${wasmModuleSrcPath}), function(err, buffer) {`, + "(installedWasmModules[wasmModuleId] = new Promise(function(resolve, reject) {", Template.indent([ - "if(err) return reject(err);", - "resolve(WebAssembly.compile(buffer));" + `require('fs').readFile(require('path').resolve(__dirname, ${ + wasmModuleSrcPath + }), function(err, buffer) {`, + Template.indent([ + "if(err) return reject(err);", + "resolve(WebAssembly.compile(buffer));" + ]), + "});" ]), - "});" + `}).then(function(module) { ${ + mainTemplate.requireFn + }.w[wasmModuleId] = module; }))` ]), - `}).then(function(module) { ${mainTemplate.requireFn}.w[wasmModuleId] = module; }))` + ");" ]), - ");", - ]), - "});", - ]); - }); - mainTemplate.hooks.requireExtensions.tap("ReadFileCompileWasmMainTemplatePlugin", (source, chunk) => { - return Template.asString([ - source, - "", - "// object with all compiled WebAssmbly.Modules", - `${mainTemplate.requireFn}.w = {};` - ]); - }); - mainTemplate.hooks.hash.tap("ReadFileCompileWasmMainTemplatePlugin", hash => { - hash.update("ReadFileCompileWasmMainTemplatePlugin"); - hash.update("1"); - hash.update(`${mainTemplate.outputOptions.webassemblyModuleFilename}`); - }); + "});" + ]); + } + ); + mainTemplate.hooks.requireExtensions.tap( + "ReadFileCompileWasmMainTemplatePlugin", + (source, chunk) => { + return Template.asString([ + source, + "", + "// object with all compiled WebAssmbly.Modules", + `${mainTemplate.requireFn}.w = {};` + ]); + } + ); + mainTemplate.hooks.hash.tap( + "ReadFileCompileWasmMainTemplatePlugin", + hash => { + hash.update("ReadFileCompileWasmMainTemplatePlugin"); + hash.update("1"); + hash.update(`${mainTemplate.outputOptions.webassemblyModuleFilename}`); + } + ); } } module.exports = ReadFileCompileWasmMainTemplatePlugin; diff --git a/lib/node/ReadFileCompileWasmTemplatePlugin.js b/lib/node/ReadFileCompileWasmTemplatePlugin.js index fc95c7da5..c5d713354 100644 --- a/lib/node/ReadFileCompileWasmTemplatePlugin.js +++ b/lib/node/ReadFileCompileWasmTemplatePlugin.js @@ -9,10 +9,17 @@ const WasmModuleTemplatePlugin = require("../wasm/WasmModuleTemplatePlugin"); class ReadFileCompileWasmTemplatePlugin { apply(compiler) { - compiler.hooks.thisCompilation.tap("ReadFileCompileWasmTemplatePlugin", (compilation) => { - new ReadFileCompileWasmMainTemplatePlugin().apply(compilation.mainTemplate); - new WasmModuleTemplatePlugin().apply(compilation.moduleTemplates.javascript); - }); + compiler.hooks.thisCompilation.tap( + "ReadFileCompileWasmTemplatePlugin", + compilation => { + new ReadFileCompileWasmMainTemplatePlugin().apply( + compilation.mainTemplate + ); + new WasmModuleTemplatePlugin().apply( + compilation.moduleTemplates.javascript + ); + } + ); } } diff --git a/lib/optimize/AggressiveMergingPlugin.js b/lib/optimize/AggressiveMergingPlugin.js index 37be35f41..e3a4c37ee 100644 --- a/lib/optimize/AggressiveMergingPlugin.js +++ b/lib/optimize/AggressiveMergingPlugin.js @@ -6,8 +6,13 @@ class AggressiveMergingPlugin { constructor(options) { - if(options !== undefined && typeof options !== "object" || Array.isArray(options)) { - throw new Error("Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/"); + if ( + (options !== undefined && typeof options !== "object") || + Array.isArray(options) + ) { + throw new Error( + "Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/" + ); } this.options = options || {}; } @@ -16,60 +21,66 @@ class AggressiveMergingPlugin { const options = this.options; const minSizeReduce = options.minSizeReduce || 1.5; - compiler.hooks.thisCompilation.tap("AggressiveMergingPlugin", (compilation) => { - compilation.hooks.optimizeChunksAdvanced.tap("AggressiveMergingPlugin", (chunks) => { - let combinations = []; - chunks.forEach((a, idx) => { - if(a.canBeInitial()) return; - for(let i = 0; i < idx; i++) { - const b = chunks[i]; - if(b.canBeInitial()) continue; - combinations.push({ - a, - b, - improvement: undefined + compiler.hooks.thisCompilation.tap( + "AggressiveMergingPlugin", + compilation => { + compilation.hooks.optimizeChunksAdvanced.tap( + "AggressiveMergingPlugin", + chunks => { + let combinations = []; + chunks.forEach((a, idx) => { + if (a.canBeInitial()) return; + for (let i = 0; i < idx; i++) { + const b = chunks[i]; + if (b.canBeInitial()) continue; + combinations.push({ + a, + b, + improvement: undefined + }); + } }); + + for (const pair of combinations) { + const a = pair.b.size({ + chunkOverhead: 0 + }); + const b = pair.a.size({ + chunkOverhead: 0 + }); + const ab = pair.b.integratedSize(pair.a, { + chunkOverhead: 0 + }); + let newSize; + if (ab === false) { + pair.improvement = false; + return; + } else { + newSize = ab; + } + + pair.improvement = (a + b) / newSize; + } + combinations = combinations.filter(pair => { + return pair.improvement !== false; + }); + combinations.sort((a, b) => { + return b.improvement - a.improvement; + }); + + const pair = combinations[0]; + + if (!pair) return; + if (pair.improvement < minSizeReduce) return; + + if (pair.b.integrate(pair.a, "aggressive-merge")) { + chunks.splice(chunks.indexOf(pair.a), 1); + return true; + } } - }); - - for(const pair of combinations) { - const a = pair.b.size({ - chunkOverhead: 0 - }); - const b = pair.a.size({ - chunkOverhead: 0 - }); - const ab = pair.b.integratedSize(pair.a, { - chunkOverhead: 0 - }); - let newSize; - if(ab === false) { - pair.improvement = false; - return; - } else { - newSize = ab; - } - - pair.improvement = (a + b) / newSize; - } - combinations = combinations.filter((pair) => { - return pair.improvement !== false; - }); - combinations.sort((a, b) => { - return b.improvement - a.improvement; - }); - - const pair = combinations[0]; - - if(!pair) return; - if(pair.improvement < minSizeReduce) return; - - if(pair.b.integrate(pair.a, "aggressive-merge")) { - chunks.splice(chunks.indexOf(pair.a), 1); - return true; - } - }); - }); + ); + } + ); } } diff --git a/lib/optimize/AggressiveSplittingPlugin.js b/lib/optimize/AggressiveSplittingPlugin.js index 16e6d2ad7..2c5b6b63d 100644 --- a/lib/optimize/AggressiveSplittingPlugin.js +++ b/lib/optimize/AggressiveSplittingPlugin.js @@ -26,219 +26,256 @@ class AggressiveSplittingPlugin { validateOptions(schema, options || {}, "Aggressive Splitting Plugin"); this.options = options || {}; - if(typeof this.options.minSize !== "number") this.options.minSize = 30 * 1024; - if(typeof this.options.maxSize !== "number") this.options.maxSize = 50 * 1024; - if(typeof this.options.chunkOverhead !== "number") this.options.chunkOverhead = 0; - if(typeof this.options.entryChunkMultiplicator !== "number") this.options.entryChunkMultiplicator = 1; - + if (typeof this.options.minSize !== "number") + this.options.minSize = 30 * 1024; + if (typeof this.options.maxSize !== "number") + this.options.maxSize = 50 * 1024; + if (typeof this.options.chunkOverhead !== "number") + this.options.chunkOverhead = 0; + if (typeof this.options.entryChunkMultiplicator !== "number") + this.options.entryChunkMultiplicator = 1; } apply(compiler) { - compiler.hooks.thisCompilation.tap("AggressiveSplittingPlugin", (compilation) => { - let needAdditionalSeal = false; - let newSplits; - let fromAggressiveSplittingSet; - let chunkSplitDataMap; - compilation.hooks.optimize.tap("AggressiveSplittingPlugin", () => { - newSplits = []; - fromAggressiveSplittingSet = new Set(); - chunkSplitDataMap = new Map(); - }); - compilation.hooks.optimizeChunksAdvanced.tap("AggressiveSplittingPlugin", (chunks) => { - // Precompute stuff - const nameToModuleMap = new Map(); - const moduleToNameMap = new Map(); - for(const m of compilation.modules) { - const name = identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache); - nameToModuleMap.set(name, m); - moduleToNameMap.set(m, name); - } - - // Check used chunk ids - const usedIds = new Set(); - for(const chunk of chunks) { - usedIds.add(chunk.id); - } - - const recordedSplits = compilation.records && compilation.records.aggressiveSplits || []; - const usedSplits = newSplits ? recordedSplits.concat(newSplits) : recordedSplits; - - const minSize = this.options.minSize; - const maxSize = this.options.maxSize; - - const applySplit = (splitData) => { - // Cannot split if id is already taken - if(splitData.id !== undefined && usedIds.has(splitData.id)) return false; - - // Get module objects from names - const selectedModules = splitData.modules.map(name => nameToModuleMap.get(name)); - - // Does the modules exist at all? - if(!selectedModules.every(Boolean)) return false; - - // Check if size matches (faster than waiting for hash) - const size = selectedModules.reduce((sum, m) => sum + m.size(), 0); - if(size !== splitData.size) return false; - - // get chunks with all modules - const selectedChunks = intersect(selectedModules.map(m => new Set(m.chunksIterable))); - - // No relevant chunks found - if(selectedChunks.size === 0) return false; - - // The found chunk is already the split or similar - if(selectedChunks.size === 1 && Array.from(selectedChunks)[0].getNumberOfModules() === selectedModules.length) { - const chunk = Array.from(selectedChunks)[0]; - if(fromAggressiveSplittingSet.has(chunk)) return false; - fromAggressiveSplittingSet.add(chunk); - chunkSplitDataMap.set(chunk, splitData); - return true; - } - - // split the chunk into two parts - const newChunk = compilation.addChunk(); - newChunk.chunkReason = "aggressive splitted"; - for(const chunk of selectedChunks) { - selectedModules.forEach(moveModuleBetween(chunk, newChunk)); - chunk.split(newChunk); - chunk.name = null; - } - fromAggressiveSplittingSet.add(newChunk); - chunkSplitDataMap.set(newChunk, splitData); - - if(splitData.id !== null && splitData.id !== undefined) { - newChunk.id = splitData.id; - } - return true; - }; - - // try to restore to recorded splitting - let changed = false; - for(let j = 0; j < usedSplits.length; j++) { - const splitData = usedSplits[j]; - if(applySplit(splitData)) - changed = true; - } - - // for any chunk which isn't splitted yet, split it and create a new entry - // start with the biggest chunk - const sortedChunks = chunks.slice().sort((a, b) => { - const diff1 = b.modulesSize() - a.modulesSize(); - if(diff1) return diff1; - const diff2 = a.getNumberOfModules() - b.getNumberOfModules(); - if(diff2) return diff2; - const modulesA = Array.from(a.modulesIterable); - const modulesB = Array.from(b.modulesIterable); - modulesA.sort(); - modulesB.sort(); - const aI = modulesA[Symbol.iterator](); - const bI = modulesB[Symbol.iterator](); - while(true) { // eslint-disable-line - const aItem = aI.next(); - const bItem = bI.next(); - if(aItem.done) return 0; - const aModuleIdentifier = aItem.value.identifier(); - const bModuleIdentifier = bItem.value.identifier(); - if(aModuleIdentifier > bModuleIdentifier) return -1; - if(aModuleIdentifier < bModuleIdentifier) return 1; - } + compiler.hooks.thisCompilation.tap( + "AggressiveSplittingPlugin", + compilation => { + let needAdditionalSeal = false; + let newSplits; + let fromAggressiveSplittingSet; + let chunkSplitDataMap; + compilation.hooks.optimize.tap("AggressiveSplittingPlugin", () => { + newSplits = []; + fromAggressiveSplittingSet = new Set(); + chunkSplitDataMap = new Map(); }); - for(const chunk of sortedChunks) { - if(fromAggressiveSplittingSet.has(chunk)) continue; - const size = chunk.modulesSize(); - if(size > maxSize && chunk.getNumberOfModules() > 1) { - const modules = chunk.getModules() - .filter(isNotAEntryModule(chunk.entryModule)) - .sort((a, b) => { - a = a.identifier(); - b = b.identifier(); - if(a > b) return 1; - if(a < b) return -1; - return 0; - }); - const selectedModules = []; - let selectedModulesSize = 0; - for(let k = 0; k < modules.length; k++) { - const module = modules[k]; - const newSize = selectedModulesSize + module.size(); - if(newSize > maxSize && selectedModulesSize >= minSize) break; - selectedModulesSize = newSize; - selectedModules.push(module); + compilation.hooks.optimizeChunksAdvanced.tap( + "AggressiveSplittingPlugin", + chunks => { + // Precompute stuff + const nameToModuleMap = new Map(); + const moduleToNameMap = new Map(); + for (const m of compilation.modules) { + const name = identifierUtils.makePathsRelative( + compiler.context, + m.identifier(), + compilation.cache + ); + nameToModuleMap.set(name, m); + moduleToNameMap.set(m, name); } - if(selectedModules.length === 0) continue; - const splitData = { - modules: selectedModules.map(m => moduleToNameMap.get(m)).sort(), - size: selectedModulesSize + + // Check used chunk ids + const usedIds = new Set(); + for (const chunk of chunks) { + usedIds.add(chunk.id); + } + + const recordedSplits = + (compilation.records && compilation.records.aggressiveSplits) || + []; + const usedSplits = newSplits + ? recordedSplits.concat(newSplits) + : recordedSplits; + + const minSize = this.options.minSize; + const maxSize = this.options.maxSize; + + const applySplit = splitData => { + // Cannot split if id is already taken + if (splitData.id !== undefined && usedIds.has(splitData.id)) + return false; + + // Get module objects from names + const selectedModules = splitData.modules.map(name => + nameToModuleMap.get(name) + ); + + // Does the modules exist at all? + if (!selectedModules.every(Boolean)) return false; + + // Check if size matches (faster than waiting for hash) + const size = selectedModules.reduce( + (sum, m) => sum + m.size(), + 0 + ); + if (size !== splitData.size) return false; + + // get chunks with all modules + const selectedChunks = intersect( + selectedModules.map(m => new Set(m.chunksIterable)) + ); + + // No relevant chunks found + if (selectedChunks.size === 0) return false; + + // The found chunk is already the split or similar + if ( + selectedChunks.size === 1 && + Array.from(selectedChunks)[0].getNumberOfModules() === + selectedModules.length + ) { + const chunk = Array.from(selectedChunks)[0]; + if (fromAggressiveSplittingSet.has(chunk)) return false; + fromAggressiveSplittingSet.add(chunk); + chunkSplitDataMap.set(chunk, splitData); + return true; + } + + // split the chunk into two parts + const newChunk = compilation.addChunk(); + newChunk.chunkReason = "aggressive splitted"; + for (const chunk of selectedChunks) { + selectedModules.forEach(moveModuleBetween(chunk, newChunk)); + chunk.split(newChunk); + chunk.name = null; + } + fromAggressiveSplittingSet.add(newChunk); + chunkSplitDataMap.set(newChunk, splitData); + + if (splitData.id !== null && splitData.id !== undefined) { + newChunk.id = splitData.id; + } + return true; }; - if(applySplit(splitData)) { - newSplits = (newSplits || []).concat(splitData); - changed = true; + // try to restore to recorded splitting + let changed = false; + for (let j = 0; j < usedSplits.length; j++) { + const splitData = usedSplits[j]; + if (applySplit(splitData)) changed = true; + } + + // for any chunk which isn't splitted yet, split it and create a new entry + // start with the biggest chunk + const sortedChunks = chunks.slice().sort((a, b) => { + const diff1 = b.modulesSize() - a.modulesSize(); + if (diff1) return diff1; + const diff2 = a.getNumberOfModules() - b.getNumberOfModules(); + if (diff2) return diff2; + const modulesA = Array.from(a.modulesIterable); + const modulesB = Array.from(b.modulesIterable); + modulesA.sort(); + modulesB.sort(); + const aI = modulesA[Symbol.iterator](); + const bI = modulesB[Symbol.iterator](); + while (true) { + // eslint-disable-line + const aItem = aI.next(); + const bItem = bI.next(); + if (aItem.done) return 0; + const aModuleIdentifier = aItem.value.identifier(); + const bModuleIdentifier = bItem.value.identifier(); + if (aModuleIdentifier > bModuleIdentifier) return -1; + if (aModuleIdentifier < bModuleIdentifier) return 1; + } + }); + for (const chunk of sortedChunks) { + if (fromAggressiveSplittingSet.has(chunk)) continue; + const size = chunk.modulesSize(); + if (size > maxSize && chunk.getNumberOfModules() > 1) { + const modules = chunk + .getModules() + .filter(isNotAEntryModule(chunk.entryModule)) + .sort((a, b) => { + a = a.identifier(); + b = b.identifier(); + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); + const selectedModules = []; + let selectedModulesSize = 0; + for (let k = 0; k < modules.length; k++) { + const module = modules[k]; + const newSize = selectedModulesSize + module.size(); + if (newSize > maxSize && selectedModulesSize >= minSize) + break; + selectedModulesSize = newSize; + selectedModules.push(module); + } + if (selectedModules.length === 0) continue; + const splitData = { + modules: selectedModules + .map(m => moduleToNameMap.get(m)) + .sort(), + size: selectedModulesSize + }; + + if (applySplit(splitData)) { + newSplits = (newSplits || []).concat(splitData); + changed = true; + } + } + } + if (changed) return true; + } + ); + compilation.hooks.recordHash.tap( + "AggressiveSplittingPlugin", + records => { + // 4. save made splittings to records + const allSplits = new Set(); + const invalidSplits = new Set(); + + // Check if some splittings are invalid + // We remove invalid splittings and try again + for (const chunk of compilation.chunks) { + const splitData = chunkSplitDataMap.get(chunk); + if (splitData !== undefined) { + if (splitData.hash && chunk.hash !== splitData.hash) { + // Split was successful, but hash doesn't equal + // We can throw away the split since it's useless now + invalidSplits.add(splitData); + } + } + } + + if (invalidSplits.size > 0) { + records.aggressiveSplits = records.aggressiveSplits.filter( + splitData => !invalidSplits.has(splitData) + ); + needAdditionalSeal = true; + } else { + // set hash and id values on all (new) splittings + for (const chunk of compilation.chunks) { + const splitData = chunkSplitDataMap.get(chunk); + if (splitData !== undefined) { + splitData.hash = chunk.hash; + splitData.id = chunk.id; + allSplits.add(splitData); + // set flag for stats + chunk.recorded = true; + } + } + + // Also add all unused historial splits (after the used ones) + // They can still be used in some future compilation + const recordedSplits = + compilation.records && compilation.records.aggressiveSplits; + if (recordedSplits) { + for (const splitData of recordedSplits) { + if (!invalidSplits.has(splitData)) allSplits.add(splitData); + } + } + + // record all splits + records.aggressiveSplits = Array.from(allSplits); + + needAdditionalSeal = false; } } - } - if(changed) - return true; - }); - compilation.hooks.recordHash.tap("AggressiveSplittingPlugin", (records) => { - // 4. save made splittings to records - const allSplits = new Set(); - const invalidSplits = new Set(); - - // Check if some splittings are invalid - // We remove invalid splittings and try again - for(const chunk of compilation.chunks) { - const splitData = chunkSplitDataMap.get(chunk); - if(splitData !== undefined) { - if(splitData.hash && chunk.hash !== splitData.hash) { - // Split was successful, but hash doesn't equal - // We can throw away the split since it's useless now - invalidSplits.add(splitData); + ); + compilation.hooks.needAdditionalSeal.tap( + "AggressiveSplittingPlugin", + () => { + if (needAdditionalSeal) { + needAdditionalSeal = false; + return true; } } - } - - if(invalidSplits.size > 0) { - - records.aggressiveSplits = records.aggressiveSplits.filter(splitData => !invalidSplits.has(splitData)); - needAdditionalSeal = true; - - } else { - - // set hash and id values on all (new) splittings - for(const chunk of compilation.chunks) { - const splitData = chunkSplitDataMap.get(chunk); - if(splitData !== undefined) { - splitData.hash = chunk.hash; - splitData.id = chunk.id; - allSplits.add(splitData); - // set flag for stats - chunk.recorded = true; - } - } - - // Also add all unused historial splits (after the used ones) - // They can still be used in some future compilation - const recordedSplits = compilation.records && compilation.records.aggressiveSplits; - if(recordedSplits) { - for(const splitData of recordedSplits) { - if(!invalidSplits.has(splitData)) - allSplits.add(splitData); - } - } - - // record all splits - records.aggressiveSplits = Array.from(allSplits); - - needAdditionalSeal = false; - } - }); - compilation.hooks.needAdditionalSeal.tap("AggressiveSplittingPlugin", () => { - if(needAdditionalSeal) { - needAdditionalSeal = false; - return true; - } - }); - }); + ); + } + ); } } module.exports = AggressiveSplittingPlugin; diff --git a/lib/optimize/ChunkModuleIdRangePlugin.js b/lib/optimize/ChunkModuleIdRangePlugin.js index 969680303..33d319747 100644 --- a/lib/optimize/ChunkModuleIdRangePlugin.js +++ b/lib/optimize/ChunkModuleIdRangePlugin.js @@ -9,15 +9,20 @@ class ChunkModuleIdRangePlugin { } apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("ChunkModuleIdRangePlugin", (compilation) => { - compilation.hooks.moduleIds.tap("ChunkModuleIdRangePlugin", (modules) => { - const chunk = this.chunks.find((chunk) => chunk.name === options.name); - if(!chunk) throw new Error("ChunkModuleIdRangePlugin: Chunk with name '" + options.name + "' was not found"); + compiler.hooks.compilation.tap("ChunkModuleIdRangePlugin", compilation => { + compilation.hooks.moduleIds.tap("ChunkModuleIdRangePlugin", modules => { + const chunk = this.chunks.find(chunk => chunk.name === options.name); + if (!chunk) + throw new Error( + "ChunkModuleIdRangePlugin: Chunk with name '" + + options.name + + "' was not found" + ); let currentId = options.start; let chunkModules; - if(options.order) { + if (options.order) { chunkModules = chunk.modules.slice(); - switch(options.order) { + switch (options.order) { case "index": chunkModules.sort((a, b) => { return a.index - b.index; @@ -29,22 +34,22 @@ class ChunkModuleIdRangePlugin { }); break; default: - throw new Error("ChunkModuleIdRangePlugin: unexpected value of order"); + throw new Error( + "ChunkModuleIdRangePlugin: unexpected value of order" + ); } - } else { - chunkModules = modules.filter((m) => { + chunkModules = modules.filter(m => { return m.chunks.includes(chunk); }); } - for(let i = 0; i < chunkModules.length; i++) { + for (let i = 0; i < chunkModules.length; i++) { const m = chunkModules[i]; - if(m.id === null) { + if (m.id === null) { m.id = currentId++; } - if(options.end && currentId > options.end) - break; + if (options.end && currentId > options.end) break; } }); }); diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js index 328fe0018..c8c12a5ce 100644 --- a/lib/optimize/ConcatenatedModule.js +++ b/lib/optimize/ConcatenatedModule.js @@ -19,54 +19,79 @@ const HarmonyExportImportedSpecifierDependency = require("../dependencies/Harmon const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); const createHash = require("../util/createHash"); -const ensureNsObjSource = (info, moduleToInfoMap, requestShortener, strictHarmonyModule) => { - if(!info.hasNamespaceObject) { +const ensureNsObjSource = ( + info, + moduleToInfoMap, + requestShortener, + strictHarmonyModule +) => { + if (!info.hasNamespaceObject) { info.hasNamespaceObject = true; const name = info.exportMap.get(true); const nsObj = [`var ${name} = {};`]; - for(const exportName of info.module.buildMeta.providedExports) { - const finalName = getFinalName(info, exportName, moduleToInfoMap, requestShortener, false, strictHarmonyModule); - nsObj.push(`__webpack_require__.d(${name}, ${JSON.stringify(exportName)}, function() { return ${finalName}; });`); + for (const exportName of info.module.buildMeta.providedExports) { + const finalName = getFinalName( + info, + exportName, + moduleToInfoMap, + requestShortener, + false, + strictHarmonyModule + ); + nsObj.push( + `__webpack_require__.d(${name}, ${JSON.stringify( + exportName + )}, function() { return ${finalName}; });` + ); } info.namespaceObjectSource = nsObj.join("\n") + "\n"; } }; -const getExternalImport = (importedModule, info, exportName, asCall, strictHarmonyModule) => { +const getExternalImport = ( + importedModule, + info, + exportName, + asCall, + strictHarmonyModule +) => { const used = importedModule.isUsed(exportName); - if(!used) return "/* unused reexport */undefined"; - const comment = used !== exportName ? ` ${Template.toNormalComment(exportName)}` : ""; - switch(importedModule.buildMeta.exportsType) { + if (!used) return "/* unused reexport */undefined"; + const comment = + used !== exportName ? ` ${Template.toNormalComment(exportName)}` : ""; + switch (importedModule.buildMeta.exportsType) { case "named": - if(exportName === "default") { + if (exportName === "default") { return info.name; - } else if(exportName === true) { + } else if (exportName === true) { info.interopNamespaceObjectUsed = true; return info.interopNamespaceObjectName; } else { break; } case "namespace": - if(exportName === true) { + if (exportName === true) { return info.name; } else { break; } default: - if(strictHarmonyModule) { - if(exportName === "default") { + if (strictHarmonyModule) { + if (exportName === "default") { return info.name; - } else if(exportName === true) { + } else if (exportName === true) { info.interopNamespaceObjectUsed = true; return info.interopNamespaceObjectName; } else { return "/* non-default import from non-esm module */undefined"; } } else { - if(exportName === "default") { + if (exportName === "default") { info.interopDefaultAccessUsed = true; - return asCall ? `${info.interopDefaultAccessName}()` : `${info.interopDefaultAccessName}.a`; - } else if(exportName === true) { + return asCall + ? `${info.interopDefaultAccessName}()` + : `${info.interopDefaultAccessName}.a`; + } else if (exportName === true) { return info.name; } else { break; @@ -74,51 +99,82 @@ const getExternalImport = (importedModule, info, exportName, asCall, strictHarmo } } const reference = `${info.name}[${JSON.stringify(used)}${comment}]`; - if(asCall) - return `Object(${reference})`; + if (asCall) return `Object(${reference})`; return reference; }; -const getFinalName = (info, exportName, moduleToInfoMap, requestShortener, asCall, strictHarmonyModule) => { - switch(info.type) { - case "concatenated": - { - const directExport = info.exportMap.get(exportName); - if(directExport) { - if(exportName === true) - ensureNsObjSource(info, moduleToInfoMap, requestShortener, strictHarmonyModule); - const name = info.internalNames.get(directExport); - if(!name) - throw new Error(`The export "${directExport}" in "${info.module.readableIdentifier(requestShortener)}" has no internal name`); - return name; - } - const reexport = info.reexportMap.get(exportName); - if(reexport) { - const refInfo = moduleToInfoMap.get(reexport.module); - if(refInfo) { - // module is in the concatenation - return getFinalName(refInfo, reexport.exportName, moduleToInfoMap, requestShortener, asCall, strictHarmonyModule); - } - } - const problem = `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` + - ` (known exports: ${Array.from(info.exportMap.keys()).filter(name => name !== true).join(" ")}, ` + - `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; - return `${Template.toNormalComment(problem)} undefined`; +const getFinalName = ( + info, + exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule +) => { + switch (info.type) { + case "concatenated": { + const directExport = info.exportMap.get(exportName); + if (directExport) { + if (exportName === true) + ensureNsObjSource( + info, + moduleToInfoMap, + requestShortener, + strictHarmonyModule + ); + const name = info.internalNames.get(directExport); + if (!name) + throw new Error( + `The export "${directExport}" in "${info.module.readableIdentifier( + requestShortener + )}" has no internal name` + ); + return name; } - case "external": - { - const importedModule = info.module; - return getExternalImport(importedModule, info, exportName, asCall, strictHarmonyModule); + const reexport = info.reexportMap.get(exportName); + if (reexport) { + const refInfo = moduleToInfoMap.get(reexport.module); + if (refInfo) { + // module is in the concatenation + return getFinalName( + refInfo, + reexport.exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule + ); + } } + const problem = + `Cannot get final name for export "${ + exportName + }" in "${info.module.readableIdentifier(requestShortener)}"` + + ` (known exports: ${Array.from(info.exportMap.keys()) + .filter(name => name !== true) + .join(" ")}, ` + + `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; + return `${Template.toNormalComment(problem)} undefined`; + } + case "external": { + const importedModule = info.module; + return getExternalImport( + importedModule, + info, + exportName, + asCall, + strictHarmonyModule + ); + } } }; const getSymbolsFromScope = (s, untilScope) => { const allUsedNames = new Set(); let scope = s; - while(scope) { - if(untilScope === scope) break; - for(const variable of scope.variables) { + while (scope) { + if (untilScope === scope) break; + for (const variable of scope.variables) { allUsedNames.add(variable.name); } scope = scope.upper; @@ -130,9 +186,9 @@ const getAllReferences = variable => { let set = variable.references; // Look for inner scope variables too (like in class Foo { t() { Foo } }) const identifiers = new Set(variable.identifiers); - for(const scope of variable.scope.childScopes) { - for(const innerVar of scope.variables) { - if(innerVar.identifiers.some(id => identifiers.has(id))) { + for (const scope of variable.scope.childScopes) { + for (const innerVar of scope.variables) { + if (innerVar.identifiers.some(id => identifiers.has(id))) { set = set.concat(innerVar.references); break; } @@ -142,25 +198,24 @@ const getAllReferences = variable => { }; const reduceSet = (a, b) => { - for(const item of b) - a.add(item); + for (const item of b) a.add(item); return a; }; const getPathInAst = (ast, node) => { - if(ast === node) { + if (ast === node) { return []; } const nr = node.range; const enterNode = n => { - if(!n) return undefined; + if (!n) return undefined; const r = n.range; - if(r) { - if(r[0] <= nr[0] && r[1] >= nr[1]) { + if (r) { + if (r[0] <= nr[0] && r[1] >= nr[1]) { const path = getPathInAst(n, node); - if(path) { + if (path) { path.push(n); return path; } @@ -170,24 +225,21 @@ const getPathInAst = (ast, node) => { }; var i; - if(Array.isArray(ast)) { - for(i = 0; i < ast.length; i++) { + if (Array.isArray(ast)) { + for (i = 0; i < ast.length; i++) { const enterResult = enterNode(ast[i]); - if(typeof enterResult !== "undefined") - return enterResult; + if (typeof enterResult !== "undefined") return enterResult; } - } else if(ast && typeof ast === "object") { + } else if (ast && typeof ast === "object") { const keys = Object.keys(ast); - for(i = 0; i < keys.length; i++) { + for (i = 0; i < keys.length; i++) { const value = ast[keys[i]]; - if(Array.isArray(value)) { + if (Array.isArray(value)) { const pathResult = getPathInAst(value, node); - if(typeof pathResult !== "undefined") - return pathResult; - } else if(value && typeof value === "object") { + if (typeof pathResult !== "undefined") return pathResult; + } else if (value && typeof value === "object") { const enterResult = enterNode(value); - if(typeof enterResult !== "undefined") - return enterResult; + if (typeof enterResult !== "undefined") return enterResult; } } } @@ -228,40 +280,51 @@ class ConcatenatedModule extends Module { // Graph const modulesSet = new Set(modules); - this.reasons = rootModule.reasons.filter(reason => !(reason.dependency instanceof HarmonyImportDependency) || !modulesSet.has(reason.module)); + this.reasons = rootModule.reasons.filter( + reason => + !(reason.dependency instanceof HarmonyImportDependency) || + !modulesSet.has(reason.module) + ); this.dependencies = []; this.warnings = []; this.errors = []; - this._orderedConcatenationList = this._createOrderedConcatenationList(rootModule, modulesSet); - for(const info of this._orderedConcatenationList) { - if(info.type === "concatenated") { + this._orderedConcatenationList = this._createOrderedConcatenationList( + rootModule, + modulesSet + ); + for (const info of this._orderedConcatenationList) { + if (info.type === "concatenated") { const m = info.module; // populate dependencies - for(const d of m.dependencies.filter(dep => !(dep instanceof HarmonyImportDependency) || !modulesSet.has(dep.module))) { + for (const d of m.dependencies.filter( + dep => + !(dep instanceof HarmonyImportDependency) || + !modulesSet.has(dep.module) + )) { this.dependencies.push(d); } // populate file dependencies - if(m.buildInfo.fileDependencies) { - for(const file of m.buildInfo.fileDependencies) { + if (m.buildInfo.fileDependencies) { + for (const file of m.buildInfo.fileDependencies) { this.buildInfo.fileDependencies.add(file); } } // populate context dependencies - if(m.buildInfo.contextDependencies) { - for(const context of m.buildInfo.contextDependencies) { + if (m.buildInfo.contextDependencies) { + for (const context of m.buildInfo.contextDependencies) { this.buildInfo.contextDependencies.add(context); } } // populate warnings - for(const warning of m.warnings) this.warnings.push(warning); + for (const warning of m.warnings) this.warnings.push(warning); // populate errors - for(const error of m.errors) this.errors.push(error); + for (const error of m.errors) this.errors.push(error); - if(m.buildInfo.assets) { - if(this.buildInfo.assets === undefined) + if (m.buildInfo.assets) { + if (this.buildInfo.assets === undefined) this.buildInfo.assets = Object.create(null); Object.assign(this.buildInfo.assets, m.buildInfo.assets); } @@ -281,7 +344,10 @@ class ConcatenatedModule extends Module { } readableIdentifier(requestShortener) { - return this.rootModule.readableIdentifier(requestShortener) + ` + ${this._numberOfConcatenatedModules - 1} modules`; + return ( + this.rootModule.readableIdentifier(requestShortener) + + ` + ${this._numberOfConcatenatedModules - 1} modules` + ); } libIdent(options) { @@ -299,7 +365,7 @@ class ConcatenatedModule extends Module { size() { // Guess size from embedded modules return this._orderedConcatenationList.reduce((sum, info) => { - switch(info.type) { + switch (info.type) { case "concatenated": return sum + info.module.size(); case "external": @@ -325,10 +391,10 @@ class ConcatenatedModule extends Module { const enterModule = getModule => { const module = getModule(); - if(!module) return; - if(set.has(module)) return; + if (!module) return; + if (set.has(module)) return; set.add(module); - if(modulesSet.has(module)) { + if (modulesSet.has(module)) { const imports = getConcatenatedImports(module); imports.forEach(enterModule); list.push({ @@ -355,9 +421,11 @@ class ConcatenatedModule extends Module { _createIdentifier() { let orderedConcatenationListIdentifiers = ""; - for(let i = 0; i < this._orderedConcatenationList.length; i++) { - if(this._orderedConcatenationList[i].type === "concatenated") { - orderedConcatenationListIdentifiers += this._orderedConcatenationList[i].module.identifier(); + for (let i = 0; i < this._orderedConcatenationList.length; i++) { + if (this._orderedConcatenationList[i].type === "concatenated") { + orderedConcatenationListIdentifiers += this._orderedConcatenationList[ + i + ].module.identifier(); orderedConcatenationListIdentifiers += " "; } } @@ -370,69 +438,69 @@ class ConcatenatedModule extends Module { const requestShortener = runtimeTemplate.requestShortener; // Metainfo for each module const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => { - switch(info.type) { - case "concatenated": - { - const exportMap = new Map(); - const reexportMap = new Map(); - for(const dep of info.module.dependencies) { - if(dep instanceof HarmonyExportSpecifierDependency) { - if(!exportMap.has(dep.name)) - exportMap.set(dep.name, dep.id); - } else if(dep instanceof HarmonyExportExpressionDependency) { - if(!exportMap.has("default")) - exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__"); - } else if(dep instanceof HarmonyExportImportedSpecifierDependency) { - const exportName = dep.name; - const importName = dep.id; - const importedModule = dep.module; - if(exportName && importName) { - if(!reexportMap.has(exportName)) { - reexportMap.set(exportName, { + switch (info.type) { + case "concatenated": { + const exportMap = new Map(); + const reexportMap = new Map(); + for (const dep of info.module.dependencies) { + if (dep instanceof HarmonyExportSpecifierDependency) { + if (!exportMap.has(dep.name)) exportMap.set(dep.name, dep.id); + } else if (dep instanceof HarmonyExportExpressionDependency) { + if (!exportMap.has("default")) + exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__"); + } else if ( + dep instanceof HarmonyExportImportedSpecifierDependency + ) { + const exportName = dep.name; + const importName = dep.id; + const importedModule = dep.module; + if (exportName && importName) { + if (!reexportMap.has(exportName)) { + reexportMap.set(exportName, { + module: importedModule, + exportName: importName, + dependency: dep + }); + } + } else if (exportName) { + if (!reexportMap.has(exportName)) { + reexportMap.set(exportName, { + module: importedModule, + exportName: true, + dependency: dep + }); + } + } else if (importedModule) { + for (const name of importedModule.buildMeta.providedExports) { + if (dep.activeExports.has(name) || name === "default") + continue; + if (!reexportMap.has(name)) { + reexportMap.set(name, { module: importedModule, - exportName: importName, + exportName: name, dependency: dep }); } - } else if(exportName) { - if(!reexportMap.has(exportName)) { - reexportMap.set(exportName, { - module: importedModule, - exportName: true, - dependency: dep - }); - } - } else if(importedModule) { - for(const name of importedModule.buildMeta.providedExports) { - if(dep.activeExports.has(name) || name === "default") - continue; - if(!reexportMap.has(name)) { - reexportMap.set(name, { - module: importedModule, - exportName: name, - dependency: dep - }); - } - } } } } - return { - type: "concatenated", - module: info.module, - index: idx, - ast: undefined, - internalSource: undefined, - source: undefined, - globalScope: undefined, - moduleScope: undefined, - internalNames: new Map(), - exportMap: exportMap, - reexportMap: reexportMap, - hasNamespaceObject: false, - namespaceObjectSource: null - }; } + return { + type: "concatenated", + module: info.module, + index: idx, + ast: undefined, + internalSource: undefined, + source: undefined, + globalScope: undefined, + moduleScope: undefined, + internalNames: new Map(), + exportMap: exportMap, + reexportMap: reexportMap, + hasNamespaceObject: false, + namespaceObjectSource: null + }; + } case "external": return { type: "external", @@ -451,59 +519,88 @@ class ConcatenatedModule extends Module { // Create mapping from module to info const moduleToInfoMap = new Map(); - for(const m of modulesWithInfo) { + for (const m of modulesWithInfo) { moduleToInfoMap.set(m.module, m); } // Configure template decorators for dependencies const innerDependencyTemplates = new Map(dependencyTemplates); - innerDependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyImportSpecifierDependency), - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyImportSideEffectDependency, new HarmonyImportSideEffectDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyImportSideEffectDependency), - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyExportSpecifierDependency), - this.rootModule - )); - innerDependencyTemplates.set(HarmonyExportExpressionDependency, new HarmonyExportExpressionDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyExportExpressionDependency), - this.rootModule, - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyExportImportedSpecifierDependency), - this.rootModule, - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyCompatibilityDependency, new HarmonyCompatibilityDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyCompatibilityDependency), - this.rootModule, - moduleToInfoMap - )); - innerDependencyTemplates.set("hash", innerDependencyTemplates.get("hash") + this.rootModule.identifier()); + innerDependencyTemplates.set( + HarmonyImportSpecifierDependency, + new HarmonyImportSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyImportSpecifierDependency), + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyImportSideEffectDependency, + new HarmonyImportSideEffectDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyImportSideEffectDependency), + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyExportSpecifierDependency, + new HarmonyExportSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportSpecifierDependency), + this.rootModule + ) + ); + innerDependencyTemplates.set( + HarmonyExportExpressionDependency, + new HarmonyExportExpressionDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportExpressionDependency), + this.rootModule, + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyExportImportedSpecifierDependency, + new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportImportedSpecifierDependency), + this.rootModule, + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyCompatibilityDependency, + new HarmonyCompatibilityDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyCompatibilityDependency), + this.rootModule, + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + "hash", + innerDependencyTemplates.get("hash") + this.rootModule.identifier() + ); // Generate source code and analyse scopes // Prepare a ReplaceSource for the final source - for(const info of modulesWithInfo) { - if(info.type === "concatenated") { + for (const info of modulesWithInfo) { + if (info.type === "concatenated") { const m = info.module; const source = m.source(innerDependencyTemplates, runtimeTemplate); const code = source.source(); let ast; try { ast = Parser.parse(code, { - sourceType: "module", + sourceType: "module" }); - } catch(err) { - if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") { + } catch (err) { + if ( + err.loc && + typeof err.loc === "object" && + typeof err.loc.line === "number" + ) { const lineNumber = err.loc.line; const lines = code.split("\n"); - err.message += "\n| " + lines.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| "); + err.message += + "\n| " + + lines + .slice(Math.max(0, lineNumber - 3), lineNumber + 2) + .join("\n| "); } throw err; } @@ -529,43 +626,212 @@ class ConcatenatedModule extends Module { const allUsedNames = new Set([ "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name - "abstract", "arguments", "async", "await", "boolean", "break", "byte", "case", "catch", "char", "class", - "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval", - "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", - "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", - "null", "package", "private", "protected", "public", "return", "short", "static", "super", - "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", - "var", "void", "volatile", "while", "with", "yield", + "abstract", + "arguments", + "async", + "await", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "eval", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "let", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "typeof", + "var", + "void", + "volatile", + "while", + "with", + "yield", - "module", "__dirname", "__filename", "exports", + "module", + "__dirname", + "__filename", + "exports", - "Array", "Date", "eval", "function", "hasOwnProperty", "Infinity", "isFinite", "isNaN", - "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String", - "toString", "undefined", "valueOf", + "Array", + "Date", + "eval", + "function", + "hasOwnProperty", + "Infinity", + "isFinite", + "isNaN", + "isPrototypeOf", + "length", + "Math", + "NaN", + "name", + "Number", + "Object", + "prototype", + "String", + "toString", + "undefined", + "valueOf", - "alert", "all", "anchor", "anchors", "area", "assign", "blur", "button", "checkbox", - "clearInterval", "clearTimeout", "clientInformation", "close", "closed", "confirm", "constructor", - "crypto", "decodeURI", "decodeURIComponent", "defaultStatus", "document", "element", "elements", - "embed", "embeds", "encodeURI", "encodeURIComponent", "escape", "event", "fileUpload", "focus", - "form", "forms", "frame", "innerHeight", "innerWidth", "layer", "layers", "link", "location", - "mimeTypes", "navigate", "navigator", "frames", "frameRate", "hidden", "history", "image", - "images", "offscreenBuffering", "open", "opener", "option", "outerHeight", "outerWidth", - "packages", "pageXOffset", "pageYOffset", "parent", "parseFloat", "parseInt", "password", "pkcs11", - "plugin", "prompt", "propertyIsEnum", "radio", "reset", "screenX", "screenY", "scroll", "secure", - "select", "self", "setInterval", "setTimeout", "status", "submit", "taint", "text", "textarea", - "top", "unescape", "untaint", "window", + "alert", + "all", + "anchor", + "anchors", + "area", + "assign", + "blur", + "button", + "checkbox", + "clearInterval", + "clearTimeout", + "clientInformation", + "close", + "closed", + "confirm", + "constructor", + "crypto", + "decodeURI", + "decodeURIComponent", + "defaultStatus", + "document", + "element", + "elements", + "embed", + "embeds", + "encodeURI", + "encodeURIComponent", + "escape", + "event", + "fileUpload", + "focus", + "form", + "forms", + "frame", + "innerHeight", + "innerWidth", + "layer", + "layers", + "link", + "location", + "mimeTypes", + "navigate", + "navigator", + "frames", + "frameRate", + "hidden", + "history", + "image", + "images", + "offscreenBuffering", + "open", + "opener", + "option", + "outerHeight", + "outerWidth", + "packages", + "pageXOffset", + "pageYOffset", + "parent", + "parseFloat", + "parseInt", + "password", + "pkcs11", + "plugin", + "prompt", + "propertyIsEnum", + "radio", + "reset", + "screenX", + "screenY", + "scroll", + "secure", + "select", + "self", + "setInterval", + "setTimeout", + "status", + "submit", + "taint", + "text", + "textarea", + "top", + "unescape", + "untaint", + "window", - "onblur", "onclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmouseover", - "onload", "onmouseup", "onmousedown", "onsubmit" + "onblur", + "onclick", + "onerror", + "onfocus", + "onkeydown", + "onkeypress", + "onkeyup", + "onmouseover", + "onload", + "onmouseup", + "onmousedown", + "onsubmit" ]); // get all global names - for(const info of modulesWithInfo) { - if(info.globalScope) { - for(const reference of info.globalScope.through) { + for (const info of modulesWithInfo) { + if (info.globalScope) { + for (const reference of info.globalScope.through) { const name = reference.identifier.name; - if(/^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?(_strict)?__$/.test(name)) { - for(const s of getSymbolsFromScope(reference.from, info.moduleScope)) { + if ( + /^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?(_strict)?__$/.test( + name + ) + ) { + for (const s of getSymbolsFromScope( + reference.from, + info.moduleScope + )) { allUsedNames.add(s); } } else { @@ -576,70 +842,107 @@ class ConcatenatedModule extends Module { } // generate names for symbols - for(const info of modulesWithInfo) { - switch(info.type) { - case "concatenated": - { - const namespaceObjectName = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(namespaceObjectName); - info.internalNames.set(namespaceObjectName, namespaceObjectName); - info.exportMap.set(true, namespaceObjectName); - for(const variable of info.moduleScope.variables) { - const name = variable.name; - if(allUsedNames.has(name)) { - const references = getAllReferences(variable); - const symbolsInReferences = references.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)).reduce(reduceSet, new Set()); - const newName = this.findNewName(name, allUsedNames, symbolsInReferences, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(newName); - info.internalNames.set(name, newName); - const source = info.source; - const allIdentifiers = new Set(references.map(r => r.identifier).concat(variable.identifiers)); - for(const identifier of allIdentifiers) { - const r = identifier.range; - const path = getPathInAst(info.ast, identifier); - if(path && path.length > 1 && path[1].type === "Property" && path[1].shorthand) { - source.insert(r[1], `: ${newName}`); - } else { - source.replace(r[0], r[1] - 1, newName); - } + for (const info of modulesWithInfo) { + switch (info.type) { + case "concatenated": { + const namespaceObjectName = this.findNewName( + "namespaceObject", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(namespaceObjectName); + info.internalNames.set(namespaceObjectName, namespaceObjectName); + info.exportMap.set(true, namespaceObjectName); + for (const variable of info.moduleScope.variables) { + const name = variable.name; + if (allUsedNames.has(name)) { + const references = getAllReferences(variable); + const symbolsInReferences = references + .map(ref => getSymbolsFromScope(ref.from, info.moduleScope)) + .reduce(reduceSet, new Set()); + const newName = this.findNewName( + name, + allUsedNames, + symbolsInReferences, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(newName); + info.internalNames.set(name, newName); + const source = info.source; + const allIdentifiers = new Set( + references.map(r => r.identifier).concat(variable.identifiers) + ); + for (const identifier of allIdentifiers) { + const r = identifier.range; + const path = getPathInAst(info.ast, identifier); + if ( + path && + path.length > 1 && + path[1].type === "Property" && + path[1].shorthand + ) { + source.insert(r[1], `: ${newName}`); + } else { + source.replace(r[0], r[1] - 1, newName); } - } else { - allUsedNames.add(name); - info.internalNames.set(name, name); } + } else { + allUsedNames.add(name); + info.internalNames.set(name, name); } - break; } - case "external": - { - const externalName = this.findNewName("", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(externalName); - info.name = externalName; - if(info.module.buildMeta.exportsType === "named" || !info.module.buildMeta.exportsType) { - const externalNameInterop = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(externalNameInterop); - info.interopNamespaceObjectName = externalNameInterop; - } - if(!info.module.buildMeta.exportsType) { - const externalNameInterop = this.findNewName("default", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(externalNameInterop); - info.interopDefaultAccessName = externalNameInterop; - } - break; + break; + } + case "external": { + const externalName = this.findNewName( + "", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalName); + info.name = externalName; + if ( + info.module.buildMeta.exportsType === "named" || + !info.module.buildMeta.exportsType + ) { + const externalNameInterop = this.findNewName( + "namespaceObject", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalNameInterop); + info.interopNamespaceObjectName = externalNameInterop; } + if (!info.module.buildMeta.exportsType) { + const externalNameInterop = this.findNewName( + "default", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalNameInterop); + info.interopDefaultAccessName = externalNameInterop; + } + break; + } } } // Find and replace referenced to modules - for(const info of modulesWithInfo) { - if(info.type === "concatenated") { - for(const reference of info.globalScope.through) { + for (const info of modulesWithInfo) { + if (info.type === "concatenated") { + for (const reference of info.globalScope.through) { const name = reference.identifier.name; - const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_strict)?__$/.exec(name); - if(match) { + const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_strict)?__$/.exec( + name + ); + if (match) { const referencedModule = modulesWithInfo[+match[1]]; let exportName; - if(match[2] === "ns") { + if (match[2] === "ns") { exportName = true; } else { const exportData = match[2]; @@ -647,7 +950,14 @@ class ConcatenatedModule extends Module { } const asCall = !!match[3]; const strictHarmonyModule = !!match[4]; - const finalName = getFinalName(referencedModule, exportName, moduleToInfoMap, requestShortener, asCall, strictHarmonyModule); + const finalName = getFinalName( + referencedModule, + exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule + ); const r = reference.identifier.range; const source = info.source; source.replace(r[0], r[1] - 1, finalName); @@ -660,38 +970,68 @@ class ConcatenatedModule extends Module { // add harmony compatibility flag (must be first because of possible circular dependencies) const usedExports = this.rootModule.usedExports; - if(usedExports === true) { - result.add(runtimeTemplate.defineEsModuleFlagStatement({ - exportsArgument: this.exportsArgument - })); + if (usedExports === true) { + result.add( + runtimeTemplate.defineEsModuleFlagStatement({ + exportsArgument: this.exportsArgument + }) + ); } // define required namespace objects (must be before evaluation modules) - for(const info of modulesWithInfo) { - if(info.namespaceObjectSource) { + for (const info of modulesWithInfo) { + if (info.namespaceObjectSource) { result.add(info.namespaceObjectSource); } } // evaluate modules in order - for(const info of modulesWithInfo) { - switch(info.type) { + for (const info of modulesWithInfo) { + switch (info.type) { case "concatenated": - result.add(`\n// CONCATENATED MODULE: ${info.module.readableIdentifier(requestShortener)}\n`); + result.add( + `\n// CONCATENATED MODULE: ${info.module.readableIdentifier( + requestShortener + )}\n` + ); result.add(info.source); break; case "external": - result.add(`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\n`); - result.add(`var ${info.name} = __webpack_require__(${JSON.stringify(info.module.id)});\n`); - if(info.interopNamespaceObjectUsed) { - if(info.module.buildMeta.exportsType === "named") { - result.add(`var ${info.interopNamespaceObjectName} = /*#__PURE__*/Object.assign({ /* fake namespace object */ }, ${info.name}, { "default": ${info.name} });\n`); - } else if(!info.module.buildMeta.exportsType) { - result.add(`var ${info.interopNamespaceObjectName} = /*#__PURE__*/{ /* fake namespace object */ "default": ${info.name} };\n`); + result.add( + `\n// EXTERNAL MODULE: ${info.module.readableIdentifier( + requestShortener + )}\n` + ); + result.add( + `var ${info.name} = __webpack_require__(${JSON.stringify( + info.module.id + )});\n` + ); + if (info.interopNamespaceObjectUsed) { + if (info.module.buildMeta.exportsType === "named") { + result.add( + `var ${ + info.interopNamespaceObjectName + } = /*#__PURE__*/Object.assign({ /* fake namespace object */ }, ${ + info.name + }, { "default": ${info.name} });\n` + ); + } else if (!info.module.buildMeta.exportsType) { + result.add( + `var ${ + info.interopNamespaceObjectName + } = /*#__PURE__*/{ /* fake namespace object */ "default": ${ + info.name + } };\n` + ); } } - if(info.interopDefaultAccessUsed) { - result.add(`var ${info.interopDefaultAccessName} = /*#__PURE__*/__webpack_require__.n(${info.name});\n`); + if (info.interopDefaultAccessUsed) { + result.add( + `var ${ + info.interopDefaultAccessName + } = /*#__PURE__*/__webpack_require__.n(${info.name});\n` + ); } break; default: @@ -705,22 +1045,31 @@ class ConcatenatedModule extends Module { findNewName(oldName, usedNamed1, usedNamed2, extraInfo) { let name = oldName; - if(name === "__WEBPACK_MODULE_DEFAULT_EXPORT__") - name = ""; + if (name === "__WEBPACK_MODULE_DEFAULT_EXPORT__") name = ""; // Remove uncool stuff - extraInfo = extraInfo.replace(/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, ""); + extraInfo = extraInfo.replace( + /\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, + "" + ); const splittedInfo = extraInfo.split("/"); - while(splittedInfo.length) { + while (splittedInfo.length) { name = splittedInfo.pop() + (name ? "_" + name : ""); const nameIdent = Template.toIdentifier(name); - if(!usedNamed1.has(nameIdent) && (!usedNamed2 || !usedNamed2.has(nameIdent))) return nameIdent; + if ( + !usedNamed1.has(nameIdent) && + (!usedNamed2 || !usedNamed2.has(nameIdent)) + ) + return nameIdent; } let i = 0; let nameWithNumber = Template.toIdentifier(`${name}_${i}`); - while(usedNamed1.has(nameWithNumber) || (usedNamed2 && usedNamed2.has(nameWithNumber))) { + while ( + usedNamed1.has(nameWithNumber) || + (usedNamed2 && usedNamed2.has(nameWithNumber)) + ) { i++; nameWithNumber = Template.toIdentifier(`${name}_${i}`); } @@ -728,8 +1077,8 @@ class ConcatenatedModule extends Module { } updateHash(hash) { - for(const info of this._orderedConcatenationList) { - switch(info.type) { + for (const info of this._orderedConcatenationList) { + switch (info.type) { case "concatenated": info.module.updateHash(hash); break; @@ -740,7 +1089,6 @@ class ConcatenatedModule extends Module { } super.updateHash(hash); } - } class HarmonyImportSpecifierDependencyConcatenatedTemplate { @@ -752,7 +1100,7 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate { getHarmonyInitOrder(dep) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { + if (!info) { return this.originalTemplate.getHarmonyInitOrder(dep); } return NaN; @@ -761,8 +1109,13 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate { harmonyInit(dep, source, runtimeTemplate, dependencyTemplates) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { - this.originalTemplate.harmonyInit(dep, source, runtimeTemplate, dependencyTemplates); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtimeTemplate, + dependencyTemplates + ); return; } } @@ -770,22 +1123,28 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate { apply(dep, source, runtime, dependencyTemplates) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { + if (!info) { this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); return; } let content; const callFlag = dep.call ? "_call" : ""; - const strictFlag = dep.originModule.buildMeta.strictHarmonyModule ? "_strict" : ""; - if(dep.id === null) { + const strictFlag = dep.originModule.buildMeta.strictHarmonyModule + ? "_strict" + : ""; + if (dep.id === null) { content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; - } else if(dep.namespaceObjectAsContext) { - content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__[${JSON.stringify(dep.id)}]`; + } else if (dep.namespaceObjectAsContext) { + content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${ + strictFlag + }__[${JSON.stringify(dep.id)}]`; } else { const exportData = Buffer.from(dep.id, "utf-8").toString("hex"); - content = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${callFlag}${strictFlag}__`; + content = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${ + callFlag + }${strictFlag}__`; } - if(dep.shorthand) { + if (dep.shorthand) { content = dep.name + ": " + content; } source.replace(dep.range[0], dep.range[1] - 1, content); @@ -801,7 +1160,7 @@ class HarmonyImportSideEffectDependencyConcatenatedTemplate { getHarmonyInitOrder(dep) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { + if (!info) { return this.originalTemplate.getHarmonyInitOrder(dep); } return NaN; @@ -810,8 +1169,13 @@ class HarmonyImportSideEffectDependencyConcatenatedTemplate { harmonyInit(dep, source, runtime, dependencyTemplates) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { - this.originalTemplate.harmonyInit(dep, source, runtime, dependencyTemplates); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); return; } } @@ -819,7 +1183,7 @@ class HarmonyImportSideEffectDependencyConcatenatedTemplate { apply(dep, source, runtime, dependencyTemplates) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { + if (!info) { this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); return; } @@ -833,21 +1197,26 @@ class HarmonyExportSpecifierDependencyConcatenatedTemplate { } getHarmonyInitOrder(dep) { - if(dep.originModule === this.rootModule) { + if (dep.originModule === this.rootModule) { return this.originalTemplate.getHarmonyInitOrder(dep); } return NaN; } harmonyInit(dep, source, runtime, dependencyTemplates) { - if(dep.originModule === this.rootModule) { - this.originalTemplate.harmonyInit(dep, source, runtime, dependencyTemplates); + if (dep.originModule === this.rootModule) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); return; } } apply(dep, source, runtime, dependencyTemplates) { - if(dep.originModule === this.rootModule) { + if (dep.originModule === this.rootModule) { this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); } } @@ -860,14 +1229,15 @@ class HarmonyExportExpressionDependencyConcatenatedTemplate { } apply(dep, source, runtime, dependencyTemplates) { - let content = "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = "; - if(dep.originModule === this.rootModule) { + let content = + "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = "; + if (dep.originModule === this.rootModule) { const used = dep.originModule.isUsed("default"); const exportsName = dep.originModule.exportsArgument; - if(used) content += `${exportsName}[${JSON.stringify(used)}] = `; + if (used) content += `${exportsName}[${JSON.stringify(used)}] = `; } - if(dep.range) { + if (dep.range) { source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "("); source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); return; @@ -886,36 +1256,42 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate { getExports(dep) { const importModule = dep.module; - if(dep.id) { + if (dep.id) { // export { named } from "module" - return [{ - name: dep.name, - id: dep.id, - module: importModule - }]; + return [ + { + name: dep.name, + id: dep.id, + module: importModule + } + ]; } - if(dep.name) { + if (dep.name) { // export * as abc from "module" - return [{ - name: dep.name, - id: true, - module: importModule - }]; + return [ + { + name: dep.name, + id: true, + module: importModule + } + ]; } // export * from "module" - return importModule.buildMeta.providedExports.filter(exp => exp !== "default" && !dep.activeExports.has(exp)).map(exp => { - return { - name: exp, - id: exp, - module: importModule - }; - }); + return importModule.buildMeta.providedExports + .filter(exp => exp !== "default" && !dep.activeExports.has(exp)) + .map(exp => { + return { + name: exp, + id: exp, + module: importModule + }; + }); } getHarmonyInitOrder(dep) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { + if (!info) { return this.originalTemplate.getHarmonyInitOrder(dep); } return NaN; @@ -924,32 +1300,48 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate { harmonyInit(dep, source, runtime, dependencyTemplates) { const module = dep.module; const info = this.modulesMap.get(module); - if(!info) { - this.originalTemplate.harmonyInit(dep, source, runtime, dependencyTemplates); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); return; } } apply(dep, source, runtime, dependencyTemplates) { - if(dep.originModule === this.rootModule) { - if(this.modulesMap.get(dep.module)) { + if (dep.originModule === this.rootModule) { + if (this.modulesMap.get(dep.module)) { const exportDefs = this.getExports(dep); - for(const def of exportDefs) { + for (const def of exportDefs) { const info = this.modulesMap.get(def.module); const used = dep.originModule.isUsed(def.name); - if(!used) { - source.insert(-1, `/* unused concated harmony import ${dep.name} */\n`); + if (!used) { + source.insert( + -1, + `/* unused concated harmony import ${dep.name} */\n` + ); } let finalName; - const strictFlag = dep.originModule.buildMeta.strictHarmonyModule ? "_strict" : ""; - if(def.id === true) { - finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; + const strictFlag = dep.originModule.buildMeta.strictHarmonyModule + ? "_strict" + : ""; + if (def.id === true) { + finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${ + strictFlag + }__`; } else { const exportData = Buffer.from(def.id, "utf-8").toString("hex"); - finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${strictFlag}__`; + finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_${ + exportData + }${strictFlag}__`; } const exportsName = this.rootModule.exportsArgument; - const content = `/* concated harmony reexport */__webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${finalName}; });\n`; + const content = `/* concated harmony reexport */__webpack_require__.d(${ + exportsName + }, ${JSON.stringify(used)}, function() { return ${finalName}; });\n`; source.insert(-1, content); } } else { diff --git a/lib/optimize/EnsureChunkConditionsPlugin.js b/lib/optimize/EnsureChunkConditionsPlugin.js index ffe0e80f2..990e712e3 100644 --- a/lib/optimize/EnsureChunkConditionsPlugin.js +++ b/lib/optimize/EnsureChunkConditionsPlugin.js @@ -7,54 +7,64 @@ const GraphHelpers = require("../GraphHelpers"); class EnsureChunkConditionsPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("EnsureChunkConditionsPlugin", (compilation) => { - const handler = (chunks) => { - let changed = false; - for(const module of compilation.modules) { - if(!module.chunkCondition) continue; - const sourceChunks = new Set(); - const chunkGroups = new Set(); - for(const chunk of module.chunksIterable) { - if(!module.chunkCondition(chunk)) { - sourceChunks.add(chunk); - for(const group of chunk.groupsIterable) { + compiler.hooks.compilation.tap( + "EnsureChunkConditionsPlugin", + compilation => { + const handler = chunks => { + let changed = false; + for (const module of compilation.modules) { + if (!module.chunkCondition) continue; + const sourceChunks = new Set(); + const chunkGroups = new Set(); + for (const chunk of module.chunksIterable) { + if (!module.chunkCondition(chunk)) { + sourceChunks.add(chunk); + for (const group of chunk.groupsIterable) { + chunkGroups.add(group); + } + } + } + if (sourceChunks.size === 0) continue; + const targetChunks = new Set(); + chunkGroupLoop: for (const chunkGroup of chunkGroups) { + // Can module be placed in a chunk of this group? + for (const chunk of chunkGroup.chunks) { + if (module.chunkCondition(chunk)) { + targetChunks.add(chunk); + continue chunkGroupLoop; + } + } + // We reached the entrypoint: fail + if (chunkGroup.isInitial()) { + throw new Error( + "Cannot fullfill chunk condition of " + module.identifier() + ); + } + // Try placing in all parents + for (const group of chunkGroup.parentsIterable) { chunkGroups.add(group); } } - } - if(sourceChunks.size === 0) continue; - const targetChunks = new Set(); - chunkGroupLoop: for(const chunkGroup of chunkGroups) { - // Can module be placed in a chunk of this group? - for(const chunk of chunkGroup.chunks) { - if(module.chunkCondition(chunk)) { - targetChunks.add(chunk); - continue chunkGroupLoop; - } + for (const sourceChunk of sourceChunks) { + GraphHelpers.disconnectChunkAndModule(sourceChunk, module); } - // We reached the entrypoint: fail - if(chunkGroup.isInitial()) { - throw new Error("Cannot fullfill chunk condition of " + module.identifier()); - } - // Try placing in all parents - for(const group of chunkGroup.parentsIterable) { - chunkGroups.add(group); + for (const targetChunk of targetChunks) { + GraphHelpers.connectChunkAndModule(targetChunk, module); } } - for(const sourceChunk of sourceChunks) { - GraphHelpers.disconnectChunkAndModule(sourceChunk, module); - } - for(const targetChunk of targetChunks) { - GraphHelpers.connectChunkAndModule(targetChunk, module); - } - } - if(changed) return true; - }; - compilation.hooks.optimizeChunksBasic.tap("EnsureChunkConditionsPlugin", handler); - compilation.hooks.optimizeExtractedChunksBasic.tap("EnsureChunkConditionsPlugin", handler); - }); + if (changed) return true; + }; + compilation.hooks.optimizeChunksBasic.tap( + "EnsureChunkConditionsPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "EnsureChunkConditionsPlugin", + handler + ); + } + ); } } module.exports = EnsureChunkConditionsPlugin; diff --git a/lib/optimize/FlagIncludedChunksPlugin.js b/lib/optimize/FlagIncludedChunksPlugin.js index fab8fd17a..a9a1e13dc 100644 --- a/lib/optimize/FlagIncludedChunksPlugin.js +++ b/lib/optimize/FlagIncludedChunksPlugin.js @@ -5,30 +5,33 @@ "use strict"; class FlagIncludedChunksPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("FlagIncludedChunksPlugin", (compilation) => { - compilation.hooks.optimizeChunkIds.tap("FlagIncludedChunksPlugin", (chunks) => { - for(const chunkA of chunks) { - loopB: for(const chunkB of chunks) { - // as we iterate the same iterables twice - // skip if we find ourselves - if(chunkA === chunkB) continue loopB; + compiler.hooks.compilation.tap("FlagIncludedChunksPlugin", compilation => { + compilation.hooks.optimizeChunkIds.tap( + "FlagIncludedChunksPlugin", + chunks => { + for (const chunkA of chunks) { + loopB: for (const chunkB of chunks) { + // as we iterate the same iterables twice + // skip if we find ourselves + if (chunkA === chunkB) continue loopB; - // instead of swapping A and B just bail - // as we loop twice the current A will be B and B then A - if(chunkA.getNumberOfModules() < chunkB.getNumberOfModules()) continue loopB; + // instead of swapping A and B just bail + // as we loop twice the current A will be B and B then A + if (chunkA.getNumberOfModules() < chunkB.getNumberOfModules()) + continue loopB; - if(chunkB.getNumberOfModules() === 0) continue loopB; + if (chunkB.getNumberOfModules() === 0) continue loopB; - // is chunkB in chunkA? - for(const m of chunkB.modulesIterable) { - if(!chunkA.containsModule(m)) continue loopB; + // is chunkB in chunkA? + for (const m of chunkB.modulesIterable) { + if (!chunkA.containsModule(m)) continue loopB; + } + chunkA.ids.push(chunkB.id); } - chunkA.ids.push(chunkB.id); } } - }); + ); }); } } diff --git a/lib/optimize/LimitChunkCountPlugin.js b/lib/optimize/LimitChunkCountPlugin.js index f301904a7..f38b942b1 100644 --- a/lib/optimize/LimitChunkCountPlugin.js +++ b/lib/optimize/LimitChunkCountPlugin.js @@ -14,44 +14,52 @@ class LimitChunkCountPlugin { } apply(compiler) { const options = this.options; - compiler.hooks.compilation.tap("LimitChunkCountPlugin", (compilation) => { - compilation.hooks.optimizeChunksAdvanced.tap("LimitChunkCountPlugin", (chunks) => { - const maxChunks = options.maxChunks; - if(!maxChunks) return; - if(maxChunks < 1) return; - if(chunks.length <= maxChunks) return; + compiler.hooks.compilation.tap("LimitChunkCountPlugin", compilation => { + compilation.hooks.optimizeChunksAdvanced.tap( + "LimitChunkCountPlugin", + chunks => { + const maxChunks = options.maxChunks; + if (!maxChunks) return; + if (maxChunks < 1) return; + if (chunks.length <= maxChunks) return; - const sortedExtendedPairCombinations = chunks.reduce((combinations, a, idx) => { - // create combination pairs - for(let i = 0; i < idx; i++) { - const b = chunks[i]; - combinations.push([b, a]); + const sortedExtendedPairCombinations = chunks + .reduce((combinations, a, idx) => { + // create combination pairs + for (let i = 0; i < idx; i++) { + const b = chunks[i]; + combinations.push([b, a]); + } + return combinations; + }, []) + .map(pair => { + // extend combination pairs with size and integrated size + const a = pair[0].size(options); + const b = pair[1].size(options); + const ab = pair[0].integratedSize(pair[1], options); + return [a + b - ab, ab, pair[0], pair[1], a, b]; + }) + .filter(extendedPair => { + // filter pairs that do not have an integratedSize + // meaning they can NOT be integrated! + return extendedPair[1] !== false; + }) + .sort((a, b) => { + // sadly javascript does an inplace sort here + // sort them by size + const diff = b[0] - a[0]; + if (diff !== 0) return diff; + return a[1] - b[1]; + }); + + const pair = sortedExtendedPairCombinations[0]; + + if (pair && pair[2].integrate(pair[3], "limit")) { + chunks.splice(chunks.indexOf(pair[3]), 1); + return true; } - return combinations; - }, []).map((pair) => { - // extend combination pairs with size and integrated size - const a = pair[0].size(options); - const b = pair[1].size(options); - const ab = pair[0].integratedSize(pair[1], options); - return [a + b - ab, ab, pair[0], pair[1], a, b]; - }).filter((extendedPair) => { - // filter pairs that do not have an integratedSize - // meaning they can NOT be integrated! - return extendedPair[1] !== false; - }).sort((a, b) => { // sadly javascript does an inplace sort here - // sort them by size - const diff = b[0] - a[0]; - if(diff !== 0) return diff; - return a[1] - b[1]; - }); - - const pair = sortedExtendedPairCombinations[0]; - - if(pair && pair[2].integrate(pair[3], "limit")) { - chunks.splice(chunks.indexOf(pair[3]), 1); - return true; } - }); + ); }); } } diff --git a/lib/optimize/MergeDuplicateChunksPlugin.js b/lib/optimize/MergeDuplicateChunksPlugin.js index 4285b2593..cc888923c 100644 --- a/lib/optimize/MergeDuplicateChunksPlugin.js +++ b/lib/optimize/MergeDuplicateChunksPlugin.js @@ -5,60 +5,71 @@ "use strict"; class MergeDuplicateChunksPlugin { - apply(compiler) { - compiler.hooks.compilation.tap("MergeDuplicateChunksPlugin", (compilation) => { - compilation.hooks.optimizeChunksBasic.tap("MergeDuplicateChunksPlugin", (chunks) => { - // remember already tested chunks for performance - const notDuplicates = new Set(); + compiler.hooks.compilation.tap( + "MergeDuplicateChunksPlugin", + compilation => { + compilation.hooks.optimizeChunksBasic.tap( + "MergeDuplicateChunksPlugin", + chunks => { + // remember already tested chunks for performance + const notDuplicates = new Set(); - // for each chunk - for(const chunk of chunks) { - - // track a Set of all chunk that could be duplicates - let possibleDuplicates; - for(const module of chunk.modulesIterable) { - if(possibleDuplicates === undefined) { - // when possibleDuplicates is not yet set, - // create a new Set from chunks of the current module - // including only chunks with the same number of modules - for(const dup of module.chunksIterable) { - if(dup !== chunk && chunk.getNumberOfModules() === dup.getNumberOfModules() && !notDuplicates.has(dup)) { - // delay allocating the new Set until here, reduce memory pressure - if(possibleDuplicates === undefined) - possibleDuplicates = new Set(); - possibleDuplicates.add(dup); + // for each chunk + for (const chunk of chunks) { + // track a Set of all chunk that could be duplicates + let possibleDuplicates; + for (const module of chunk.modulesIterable) { + if (possibleDuplicates === undefined) { + // when possibleDuplicates is not yet set, + // create a new Set from chunks of the current module + // including only chunks with the same number of modules + for (const dup of module.chunksIterable) { + if ( + dup !== chunk && + chunk.getNumberOfModules() === dup.getNumberOfModules() && + !notDuplicates.has(dup) + ) { + // delay allocating the new Set until here, reduce memory pressure + if (possibleDuplicates === undefined) + possibleDuplicates = new Set(); + possibleDuplicates.add(dup); + } + } + // when no chunk is possible we can break here + if (possibleDuplicates === undefined) break; + } else { + // validate existing possible duplicates + for (const dup of possibleDuplicates) { + // remove possible duplicate when module is not contained + if (!dup.containsModule(module)) + possibleDuplicates.delete(dup); + } + // when all chunks has been removed we can break here + if (possibleDuplicates.size === 0) break; } } - // when no chunk is possible we can break here - if(possibleDuplicates === undefined) break; - } else { - // validate existing possible duplicates - for(const dup of possibleDuplicates) { - // remove possible duplicate when module is not contained - if(!dup.containsModule(module)) - possibleDuplicates.delete(dup); + + // when we found duplicates + if ( + possibleDuplicates !== undefined && + possibleDuplicates.size > 0 + ) { + for (const otherChunk of possibleDuplicates) { + if (otherChunk.hasRuntime() !== chunk.hasRuntime()) continue; + // merge them + if (chunk.integrate(otherChunk, "duplicate")) + chunks.splice(chunks.indexOf(otherChunk), 1); + } } - // when all chunks has been removed we can break here - if(possibleDuplicates.size === 0) break; + + // don't check already processed chunks twice + notDuplicates.add(chunk); } } - - // when we found duplicates - if(possibleDuplicates !== undefined && possibleDuplicates.size > 0) { - for(const otherChunk of possibleDuplicates) { - if(otherChunk.hasRuntime() !== chunk.hasRuntime()) continue; - // merge them - if(chunk.integrate(otherChunk, "duplicate")) - chunks.splice(chunks.indexOf(otherChunk), 1); - } - } - - // don't check already processed chunks twice - notDuplicates.add(chunk); - } - }); - }); + ); + } + ); } } module.exports = MergeDuplicateChunksPlugin; diff --git a/lib/optimize/MinChunkSizePlugin.js b/lib/optimize/MinChunkSizePlugin.js index 1d79a2709..0f3893910 100644 --- a/lib/optimize/MinChunkSizePlugin.js +++ b/lib/optimize/MinChunkSizePlugin.js @@ -16,50 +16,61 @@ class MinChunkSizePlugin { apply(compiler) { const options = this.options; const minChunkSize = options.minChunkSize; - compiler.hooks.compilation.tap("MinChunkSizePlugin", (compilation) => { - compilation.hooks.optimizeChunksAdvanced.tap("MinChunkSizePlugin", (chunks) => { - const equalOptions = { - chunkOverhead: 1, - entryChunkMultiplicator: 1 - }; + compiler.hooks.compilation.tap("MinChunkSizePlugin", compilation => { + compilation.hooks.optimizeChunksAdvanced.tap( + "MinChunkSizePlugin", + chunks => { + const equalOptions = { + chunkOverhead: 1, + entryChunkMultiplicator: 1 + }; - const sortedSizeFilteredExtendedPairCombinations = chunks.reduce((combinations, a, idx) => { - // create combination pairs - for(let i = 0; i < idx; i++) { - const b = chunks[i]; - combinations.push([b, a]); - } - return combinations; - }, []).filter((pair) => { - // check if one of the chunks sizes is smaller than the minChunkSize - const p0SmallerThanMinChunkSize = pair[0].size(equalOptions) < minChunkSize; - const p1SmallerThanMinChunkSize = pair[1].size(equalOptions) < minChunkSize; - return p0SmallerThanMinChunkSize || p1SmallerThanMinChunkSize; - }).map((pair) => { - // extend combination pairs with size and integrated size - const a = pair[0].size(options); - const b = pair[1].size(options); - const ab = pair[0].integratedSize(pair[1], options); - return [a + b - ab, ab, pair[0], pair[1]]; - }).filter((pair) => { - // filter pairs that do not have an integratedSize - // meaning they can NOT be integrated! - return pair[1] !== false; - }).sort((a, b) => { // sadly javascript does an inplace sort here - // sort by size - const diff = b[0] - a[0]; - if(diff !== 0) return diff; - return a[1] - b[1]; - }); + const sortedSizeFilteredExtendedPairCombinations = chunks + .reduce((combinations, a, idx) => { + // create combination pairs + for (let i = 0; i < idx; i++) { + const b = chunks[i]; + combinations.push([b, a]); + } + return combinations; + }, []) + .filter(pair => { + // check if one of the chunks sizes is smaller than the minChunkSize + const p0SmallerThanMinChunkSize = + pair[0].size(equalOptions) < minChunkSize; + const p1SmallerThanMinChunkSize = + pair[1].size(equalOptions) < minChunkSize; + return p0SmallerThanMinChunkSize || p1SmallerThanMinChunkSize; + }) + .map(pair => { + // extend combination pairs with size and integrated size + const a = pair[0].size(options); + const b = pair[1].size(options); + const ab = pair[0].integratedSize(pair[1], options); + return [a + b - ab, ab, pair[0], pair[1]]; + }) + .filter(pair => { + // filter pairs that do not have an integratedSize + // meaning they can NOT be integrated! + return pair[1] !== false; + }) + .sort((a, b) => { + // sadly javascript does an inplace sort here + // sort by size + const diff = b[0] - a[0]; + if (diff !== 0) return diff; + return a[1] - b[1]; + }); - if(sortedSizeFilteredExtendedPairCombinations.length === 0) return; + if (sortedSizeFilteredExtendedPairCombinations.length === 0) return; - const pair = sortedSizeFilteredExtendedPairCombinations[0]; + const pair = sortedSizeFilteredExtendedPairCombinations[0]; - pair[2].integrate(pair[3], "min-size"); - chunks.splice(chunks.indexOf(pair[3]), 1); - return true; - }); + pair[2].integrate(pair[3], "min-size"); + chunks.splice(chunks.indexOf(pair[3]), 1); + return true; + } + ); }); } } diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index ff44e535f..4b9f5e3d8 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -17,240 +17,333 @@ const formatBailoutReason = msg => { class ModuleConcatenationPlugin { constructor(options) { - if(typeof options !== "object") options = {}; + if (typeof options !== "object") options = {}; this.options = options; } apply(compiler) { - compiler.hooks.compilation.tap("ModuleConcatenationPlugin", (compilation, { - normalModuleFactory - }) => { - const handler = (parser, parserOptions) => { - parser.hooks.call.for("eval").tap("ModuleConcatenationPlugin", () => { - // Because of variable renaming we can't use modules with eval. - parser.state.module.buildMeta.moduleConcatenationBailout = "eval()"; - }); - }; + compiler.hooks.compilation.tap( + "ModuleConcatenationPlugin", + (compilation, { normalModuleFactory }) => { + const handler = (parser, parserOptions) => { + parser.hooks.call.for("eval").tap("ModuleConcatenationPlugin", () => { + // Because of variable renaming we can't use modules with eval. + parser.state.module.buildMeta.moduleConcatenationBailout = "eval()"; + }); + }; - normalModuleFactory.hooks.parser.for("javascript/auto").tap("ModuleConcatenationPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ModuleConcatenationPlugin", handler); - normalModuleFactory.hooks.parser.for("javascript/esm").tap("ModuleConcatenationPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ModuleConcatenationPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ModuleConcatenationPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ModuleConcatenationPlugin", handler); - const bailoutReasonMap = new Map(); + const bailoutReasonMap = new Map(); - const setBailoutReason = (module, reason) => { - bailoutReasonMap.set(module, reason); - module.optimizationBailout.push(typeof reason === "function" ? (rs) => formatBailoutReason(reason(rs)) : formatBailoutReason(reason)); - }; + const setBailoutReason = (module, reason) => { + bailoutReasonMap.set(module, reason); + module.optimizationBailout.push( + typeof reason === "function" + ? rs => formatBailoutReason(reason(rs)) + : formatBailoutReason(reason) + ); + }; - const getBailoutReason = (module, requestShortener) => { - const reason = bailoutReasonMap.get(module); - if(typeof reason === "function") return reason(requestShortener); - return reason; - }; + const getBailoutReason = (module, requestShortener) => { + const reason = bailoutReasonMap.get(module); + if (typeof reason === "function") return reason(requestShortener); + return reason; + }; - compilation.hooks.optimizeChunkModules.tap("ModuleConcatenationPlugin", (chunks, modules) => { - const relevantModules = []; - const possibleInners = new Set(); - for(const module of modules) { - // Only harmony modules are valid for optimization - if(!module.buildMeta || module.buildMeta.exportsType !== "namespace" || !module.dependencies.some(d => d instanceof HarmonyCompatibilityDependency)) { - setBailoutReason(module, "Module is not an ECMAScript module"); - continue; - } + compilation.hooks.optimizeChunkModules.tap( + "ModuleConcatenationPlugin", + (chunks, modules) => { + const relevantModules = []; + const possibleInners = new Set(); + for (const module of modules) { + // Only harmony modules are valid for optimization + if ( + !module.buildMeta || + module.buildMeta.exportsType !== "namespace" || + !module.dependencies.some( + d => d instanceof HarmonyCompatibilityDependency + ) + ) { + setBailoutReason(module, "Module is not an ECMAScript module"); + continue; + } - // Some expressions are not compatible with module concatenation - // because they may produce unexpected results. The plugin bails out - // if some were detected upfront. - if(module.buildMeta && module.buildMeta.moduleConcatenationBailout) { - setBailoutReason(module, `Module uses ${module.buildMeta.moduleConcatenationBailout}`); - continue; - } + // Some expressions are not compatible with module concatenation + // because they may produce unexpected results. The plugin bails out + // if some were detected upfront. + if ( + module.buildMeta && + module.buildMeta.moduleConcatenationBailout + ) { + setBailoutReason( + module, + `Module uses ${module.buildMeta.moduleConcatenationBailout}` + ); + continue; + } - // Exports must be known (and not dynamic) - if(!Array.isArray(module.buildMeta.providedExports)) { - setBailoutReason(module, "Module exports are unknown"); - continue; - } + // Exports must be known (and not dynamic) + if (!Array.isArray(module.buildMeta.providedExports)) { + setBailoutReason(module, "Module exports are unknown"); + continue; + } - // Using dependency variables is not possible as this wraps the code in a function - if(module.variables.length > 0) { - setBailoutReason(module, `Module uses injected variables (${module.variables.map(v => v.name).join(", ")})`); - continue; - } + // Using dependency variables is not possible as this wraps the code in a function + if (module.variables.length > 0) { + setBailoutReason( + module, + `Module uses injected variables (${module.variables + .map(v => v.name) + .join(", ")})` + ); + continue; + } - // Hot Module Replacement need it's own module to work correctly - if(module.dependencies.some(dep => dep instanceof ModuleHotAcceptDependency || dep instanceof ModuleHotDeclineDependency)) { - setBailoutReason(module, "Module uses Hot Module Replacement"); - continue; - } + // Hot Module Replacement need it's own module to work correctly + if ( + module.dependencies.some( + dep => + dep instanceof ModuleHotAcceptDependency || + dep instanceof ModuleHotDeclineDependency + ) + ) { + setBailoutReason(module, "Module uses Hot Module Replacement"); + continue; + } - relevantModules.push(module); + relevantModules.push(module); - // Module must not be the entry points - if(module.isEntryModule()) { - setBailoutReason(module, "Module is an entry point"); - continue; - } + // Module must not be the entry points + if (module.isEntryModule()) { + setBailoutReason(module, "Module is an entry point"); + continue; + } - // Module must be in any chunk (we don't want to do useless work) - if(module.getNumberOfChunks() === 0) { - setBailoutReason(module, "Module is not in any chunk"); - continue; - } + // Module must be in any chunk (we don't want to do useless work) + if (module.getNumberOfChunks() === 0) { + setBailoutReason(module, "Module is not in any chunk"); + continue; + } - // Module must only be used by Harmony Imports - const nonHarmonyReasons = module.reasons.filter(reason => !reason.dependency || !(reason.dependency instanceof HarmonyImportDependency)); - if(nonHarmonyReasons.length > 0) { - const importingModules = new Set(nonHarmonyReasons.map(r => r.module).filter(Boolean)); - const importingExplanations = new Set(nonHarmonyReasons.map(r => r.explanation).filter(Boolean)); - const importingModuleTypes = new Map(Array.from(importingModules).map(m => [m, new Set(nonHarmonyReasons.filter(r => r.module === m).map(r => r.dependency.type).sort())])); - setBailoutReason(module, (requestShortener) => { - const names = Array.from(importingModules).map(m => `${m.readableIdentifier(requestShortener)} (referenced with ${Array.from(importingModuleTypes.get(m)).join(", ")})`).sort(); - const explanations = Array.from(importingExplanations).sort(); - if(names.length > 0 && explanations.length === 0) - return `Module is referenced from these modules with unsupported syntax: ${names.join(", ")}`; - else if(names.length === 0 && explanations.length > 0) - return `Module is referenced by: ${explanations.join(", ")}`; - else if(names.length > 0 && explanations.length > 0) - return `Module is referenced from these modules with unsupported syntax: ${names.join(", ")} and by: ${explanations.join(", ")}`; - else - return "Module is referenced in a unsupported way"; + // Module must only be used by Harmony Imports + const nonHarmonyReasons = module.reasons.filter( + reason => + !reason.dependency || + !(reason.dependency instanceof HarmonyImportDependency) + ); + if (nonHarmonyReasons.length > 0) { + const importingModules = new Set( + nonHarmonyReasons.map(r => r.module).filter(Boolean) + ); + const importingExplanations = new Set( + nonHarmonyReasons.map(r => r.explanation).filter(Boolean) + ); + const importingModuleTypes = new Map( + Array.from(importingModules).map(m => [ + m, + new Set( + nonHarmonyReasons + .filter(r => r.module === m) + .map(r => r.dependency.type) + .sort() + ) + ]) + ); + setBailoutReason(module, requestShortener => { + const names = Array.from(importingModules) + .map( + m => + `${m.readableIdentifier( + requestShortener + )} (referenced with ${Array.from( + importingModuleTypes.get(m) + ).join(", ")})` + ) + .sort(); + const explanations = Array.from(importingExplanations).sort(); + if (names.length > 0 && explanations.length === 0) + return `Module is referenced from these modules with unsupported syntax: ${names.join( + ", " + )}`; + else if (names.length === 0 && explanations.length > 0) + return `Module is referenced by: ${explanations.join( + ", " + )}`; + else if (names.length > 0 && explanations.length > 0) + return `Module is referenced from these modules with unsupported syntax: ${names.join( + ", " + )} and by: ${explanations.join(", ")}`; + else return "Module is referenced in a unsupported way"; + }); + continue; + } + + possibleInners.add(module); + } + // sort by depth + // modules with lower depth are more likely suited as roots + // this improves performance, because modules already selected as inner are skipped + relevantModules.sort((a, b) => { + return a.depth - b.depth; }); - continue; - } + const concatConfigurations = []; + const usedAsInner = new Set(); + for (const currentRoot of relevantModules) { + // when used by another configuration as inner: + // the other configuration is better and we can skip this one + if (usedAsInner.has(currentRoot)) continue; - possibleInners.add(module); - } - // sort by depth - // modules with lower depth are more likely suited as roots - // this improves performance, because modules already selected as inner are skipped - relevantModules.sort((a, b) => { - return a.depth - b.depth; - }); - const concatConfigurations = []; - const usedAsInner = new Set(); - for(const currentRoot of relevantModules) { - // when used by another configuration as inner: - // the other configuration is better and we can skip this one - if(usedAsInner.has(currentRoot)) - continue; + // create a configuration with the root + const currentConfiguration = new ConcatConfiguration(currentRoot); - // create a configuration with the root - const currentConfiguration = new ConcatConfiguration(currentRoot); + // cache failures to add modules + const failureCache = new Map(); - // cache failures to add modules - const failureCache = new Map(); - - // try to add all imports - for(const imp of this.getImports(currentRoot)) { - const problem = this.tryToAdd(currentConfiguration, imp, possibleInners, failureCache); - if(problem) { - failureCache.set(imp, problem); - currentConfiguration.addWarning(imp, problem); - } - } - if(!currentConfiguration.isEmpty()) { - concatConfigurations.push(currentConfiguration); - for(const module of currentConfiguration.getModules()) { - if(module !== currentConfiguration.rootModule) - usedAsInner.add(module); - } - } - } - // HACK: Sort configurations by length and start with the longest one - // to get the biggers groups possible. Used modules are marked with usedModules - // TODO: Allow to reuse existing configuration while trying to add dependencies. - // This would improve performance. O(n^2) -> O(n) - concatConfigurations.sort((a, b) => { - return b.modules.size - a.modules.size; - }); - const usedModules = new Set(); - for(const concatConfiguration of concatConfigurations) { - if(usedModules.has(concatConfiguration.rootModule)) - continue; - const modules = concatConfiguration.getModules(); - const newModule = new ConcatenatedModule(concatConfiguration.rootModule, modules); - for(const warning of concatConfiguration.getWarningsSorted()) { - newModule.optimizationBailout.push((requestShortener) => { - const reason = getBailoutReason(warning[0], requestShortener); - const reasonWithPrefix = reason ? ` (<- ${reason})` : ""; - if(warning[0] === warning[1]) - return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)}${reasonWithPrefix}`); - else - return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)} because of ${warning[1].readableIdentifier(requestShortener)}${reasonWithPrefix}`); - }); - } - const chunks = concatConfiguration.rootModule.getChunks(); - for(const m of modules) { - usedModules.add(m); - for(const chunk of chunks) { - chunk.removeModule(m); - } - } - for(const chunk of chunks) { - chunk.addModule(newModule); - newModule.addChunk(chunk); - if(chunk.entryModule === concatConfiguration.rootModule) - chunk.entryModule = newModule; - } - compilation.modules.push(newModule); - for(const reason of newModule.reasons) { - reason.dependency.module = newModule; - } - for(const dep of newModule.dependencies) { - if(dep.module) { - for(const reason of dep.module.reasons) { - if(reason.dependency === dep) - reason.module = newModule; + // try to add all imports + for (const imp of this.getImports(currentRoot)) { + const problem = this.tryToAdd( + currentConfiguration, + imp, + possibleInners, + failureCache + ); + if (problem) { + failureCache.set(imp, problem); + currentConfiguration.addWarning(imp, problem); + } + } + if (!currentConfiguration.isEmpty()) { + concatConfigurations.push(currentConfiguration); + for (const module of currentConfiguration.getModules()) { + if (module !== currentConfiguration.rootModule) + usedAsInner.add(module); + } } } + // HACK: Sort configurations by length and start with the longest one + // to get the biggers groups possible. Used modules are marked with usedModules + // TODO: Allow to reuse existing configuration while trying to add dependencies. + // This would improve performance. O(n^2) -> O(n) + concatConfigurations.sort((a, b) => { + return b.modules.size - a.modules.size; + }); + const usedModules = new Set(); + for (const concatConfiguration of concatConfigurations) { + if (usedModules.has(concatConfiguration.rootModule)) continue; + const modules = concatConfiguration.getModules(); + const newModule = new ConcatenatedModule( + concatConfiguration.rootModule, + modules + ); + for (const warning of concatConfiguration.getWarningsSorted()) { + newModule.optimizationBailout.push(requestShortener => { + const reason = getBailoutReason(warning[0], requestShortener); + const reasonWithPrefix = reason ? ` (<- ${reason})` : ""; + if (warning[0] === warning[1]) + return formatBailoutReason( + `Cannot concat with ${warning[0].readableIdentifier( + requestShortener + )}${reasonWithPrefix}` + ); + else + return formatBailoutReason( + `Cannot concat with ${warning[0].readableIdentifier( + requestShortener + )} because of ${warning[1].readableIdentifier( + requestShortener + )}${reasonWithPrefix}` + ); + }); + } + const chunks = concatConfiguration.rootModule.getChunks(); + for (const m of modules) { + usedModules.add(m); + for (const chunk of chunks) { + chunk.removeModule(m); + } + } + for (const chunk of chunks) { + chunk.addModule(newModule); + newModule.addChunk(chunk); + if (chunk.entryModule === concatConfiguration.rootModule) + chunk.entryModule = newModule; + } + compilation.modules.push(newModule); + for (const reason of newModule.reasons) { + reason.dependency.module = newModule; + } + for (const dep of newModule.dependencies) { + if (dep.module) { + for (const reason of dep.module.reasons) { + if (reason.dependency === dep) reason.module = newModule; + } + } + } + } + compilation.modules = compilation.modules.filter( + m => !usedModules.has(m) + ); } - } - compilation.modules = compilation.modules.filter(m => !usedModules.has(m)); - }); - }); + ); + } + ); } getImports(module) { - return Array.from(new Set(module.dependencies + return Array.from( + new Set( + module.dependencies - // Only harmony Dependencies - .filter(dep => dep instanceof HarmonyImportDependency && dep.module) + // Only harmony Dependencies + .filter(dep => dep instanceof HarmonyImportDependency && dep.module) - // Get reference info for this dependency - .map(dep => dep.getReference()) + // Get reference info for this dependency + .map(dep => dep.getReference()) - // Reference is valid and has a module - .filter(ref => ref && ref.module) + // Reference is valid and has a module + .filter(ref => ref && ref.module) - // Dependencies are simple enough to concat them - .filter(ref => Array.isArray(ref.importedNames) || Array.isArray(ref.module.buildMeta.providedExports)) + // Dependencies are simple enough to concat them + .filter( + ref => + Array.isArray(ref.importedNames) || + Array.isArray(ref.module.buildMeta.providedExports) + ) - // Take the imported module - .map(ref => ref.module) - )); + // Take the imported module + .map(ref => ref.module) + ) + ); } tryToAdd(config, module, possibleModules, failureCache) { const cacheEntry = failureCache.get(module); - if(cacheEntry) { + if (cacheEntry) { return cacheEntry; } // Already added? - if(config.has(module)) { + if (config.has(module)) { return null; } // Not possible to add? - if(!possibleModules.has(module)) { + if (!possibleModules.has(module)) { failureCache.set(module, module); // cache failures for performance return module; } // module must be in the same chunks - if(!config.rootModule.hasEqualsChunks(module)) { + if (!config.rootModule.hasEqualsChunks(module)) { failureCache.set(module, module); // cache failures for performance return module; } @@ -262,22 +355,35 @@ class ModuleConcatenationPlugin { testConfig.add(module); // Every module which depends on the added module must be in the configuration too. - for(const reason of module.reasons) { - + for (const reason of module.reasons) { // Modules that are not used can be ignored - if(reason.module.factoryMeta.sideEffectFree && reason.module.used === false) continue; + if ( + reason.module.factoryMeta.sideEffectFree && + reason.module.used === false + ) + continue; - const problem = this.tryToAdd(testConfig, reason.module, possibleModules, failureCache); - if(problem) { + const problem = this.tryToAdd( + testConfig, + reason.module, + possibleModules, + failureCache + ); + if (problem) { failureCache.set(module, problem); // cache failures for performance return problem; } } // Eagerly try to add imports too if possible - for(const imp of this.getImports(module)) { - const problem = this.tryToAdd(testConfig, imp, possibleModules, failureCache); - if(problem) { + for (const imp of this.getImports(module)) { + const problem = this.tryToAdd( + testConfig, + imp, + possibleModules, + failureCache + ); + if (problem) { config.addWarning(module, problem); } } @@ -291,7 +397,7 @@ class ModuleConcatenationPlugin { class ConcatConfiguration { constructor(rootModule, cloneFrom) { this.rootModule = rootModule; - if(cloneFrom) { + if (cloneFrom) { this.modules = cloneFrom.modules.createChild(5); this.warnings = cloneFrom.warnings.createChild(5); } else { @@ -318,13 +424,15 @@ class ConcatConfiguration { } getWarningsSorted() { - return new Map(this.warnings.asPairArray().sort((a, b) => { - const ai = a[0].identifier(); - const bi = b[0].identifier(); - if(ai < bi) return -1; - if(ai > bi) return 1; - return 0; - })); + return new Map( + this.warnings.asPairArray().sort((a, b) => { + const ai = a[0].identifier(); + const bi = b[0].identifier(); + if (ai < bi) return -1; + if (ai > bi) return 1; + return 0; + }) + ); } getModules() { diff --git a/lib/optimize/OccurrenceOrderPlugin.js b/lib/optimize/OccurrenceOrderPlugin.js index 6b120dc07..613e403b6 100644 --- a/lib/optimize/OccurrenceOrderPlugin.js +++ b/lib/optimize/OccurrenceOrderPlugin.js @@ -6,106 +6,119 @@ class OccurrenceOrderPlugin { constructor(preferEntry) { - if(preferEntry !== undefined && typeof preferEntry !== "boolean") { - throw new Error("Argument should be a boolean.\nFor more info on this plugin, see https://webpack.js.org/plugins/"); + if (preferEntry !== undefined && typeof preferEntry !== "boolean") { + throw new Error( + "Argument should be a boolean.\nFor more info on this plugin, see https://webpack.js.org/plugins/" + ); } this.preferEntry = preferEntry; } apply(compiler) { const preferEntry = this.preferEntry; - compiler.hooks.compilation.tap("OccurrenceOrderPlugin", (compilation) => { - compilation.hooks.optimizeModuleOrder.tap("OccurrenceOrderPlugin", (modules) => { - const occursInInitialChunksMap = new Map(); - const occursInAllChunksMap = new Map(); + compiler.hooks.compilation.tap("OccurrenceOrderPlugin", compilation => { + compilation.hooks.optimizeModuleOrder.tap( + "OccurrenceOrderPlugin", + modules => { + const occursInInitialChunksMap = new Map(); + const occursInAllChunksMap = new Map(); - const initialChunkChunkMap = new Map(); - const entryCountMap = new Map(); - for(const m of modules) { - let initial = 0; - let entry = 0; - for(const c of m.chunksIterable) { - if(c.canBeInitial()) initial++; - if(c.entryModule === m) entry++; + const initialChunkChunkMap = new Map(); + const entryCountMap = new Map(); + for (const m of modules) { + let initial = 0; + let entry = 0; + for (const c of m.chunksIterable) { + if (c.canBeInitial()) initial++; + if (c.entryModule === m) entry++; + } + initialChunkChunkMap.set(m, initial); + entryCountMap.set(m, entry); } - initialChunkChunkMap.set(m, initial); - entryCountMap.set(m, entry); - } - const countOccursInEntry = (sum, r) => { - if(!r.module) return sum; - return sum + initialChunkChunkMap.get(r.module); - }; - const countOccurs = (sum, r) => { - if(!r.module) return sum; - let factor = 1; - if(typeof r.dependency.getNumberOfIdOccurrences === "function") - factor = r.dependency.getNumberOfIdOccurrences(); - if(factor === 0) return sum; - return sum + factor * r.module.getNumberOfChunks(); - }; + const countOccursInEntry = (sum, r) => { + if (!r.module) return sum; + return sum + initialChunkChunkMap.get(r.module); + }; + const countOccurs = (sum, r) => { + if (!r.module) return sum; + let factor = 1; + if (typeof r.dependency.getNumberOfIdOccurrences === "function") + factor = r.dependency.getNumberOfIdOccurrences(); + if (factor === 0) return sum; + return sum + factor * r.module.getNumberOfChunks(); + }; - if(preferEntry) { - for(const m of modules) { - const result = m.reasons.reduce(countOccursInEntry, 0) + initialChunkChunkMap.get(m) + entryCountMap.get(m); - occursInInitialChunksMap.set(m, result); - } - } - - const originalOrder = new Map(); - let i = 0; - for(const m of modules) { - const result = m.reasons.reduce(countOccurs, 0) + m.getNumberOfChunks() + entryCountMap.get(m); - occursInAllChunksMap.set(m, result); - originalOrder.set(m, i++); - } - - modules.sort((a, b) => { - if(preferEntry) { - const aEntryOccurs = occursInInitialChunksMap.get(a); - const bEntryOccurs = occursInInitialChunksMap.get(b); - if(aEntryOccurs > bEntryOccurs) return -1; - if(aEntryOccurs < bEntryOccurs) return 1; - } - const aOccurs = occursInAllChunksMap.get(a); - const bOccurs = occursInAllChunksMap.get(b); - if(aOccurs > bOccurs) return -1; - if(aOccurs < bOccurs) return 1; - const orgA = originalOrder.get(a); - const orgB = originalOrder.get(b); - return orgB - orgA; - }); - }); - compilation.hooks.optimizeChunkOrder.tap("OccurrenceOrderPlugin", (chunks) => { - const occursInInitialChunksMap = new Map(); - const originalOrder = new Map(); - - let i = 0; - for(const c of chunks) { - let occurs = 0; - for(const chunkGroup of c.groupsIterable) { - for(const parent of chunkGroup.parentsIterable) { - if(parent.isInitial()) - occurs++; + if (preferEntry) { + for (const m of modules) { + const result = + m.reasons.reduce(countOccursInEntry, 0) + + initialChunkChunkMap.get(m) + + entryCountMap.get(m); + occursInInitialChunksMap.set(m, result); } } - occursInInitialChunksMap.set(c, occurs); - originalOrder.set(c, i++); - } - chunks.sort((a, b) => { - const aEntryOccurs = occursInInitialChunksMap.get(a); - const bEntryOccurs = occursInInitialChunksMap.get(b); - if(aEntryOccurs > bEntryOccurs) return -1; - if(aEntryOccurs < bEntryOccurs) return 1; - const aOccurs = a.getNumberOfGroups(); - const bOccurs = b.getNumberOfGroups(); - if(aOccurs > bOccurs) return -1; - if(aOccurs < bOccurs) return 1; - const orgA = originalOrder.get(a); - const orgB = originalOrder.get(b); - return orgB - orgA; - }); - }); + const originalOrder = new Map(); + let i = 0; + for (const m of modules) { + const result = + m.reasons.reduce(countOccurs, 0) + + m.getNumberOfChunks() + + entryCountMap.get(m); + occursInAllChunksMap.set(m, result); + originalOrder.set(m, i++); + } + + modules.sort((a, b) => { + if (preferEntry) { + const aEntryOccurs = occursInInitialChunksMap.get(a); + const bEntryOccurs = occursInInitialChunksMap.get(b); + if (aEntryOccurs > bEntryOccurs) return -1; + if (aEntryOccurs < bEntryOccurs) return 1; + } + const aOccurs = occursInAllChunksMap.get(a); + const bOccurs = occursInAllChunksMap.get(b); + if (aOccurs > bOccurs) return -1; + if (aOccurs < bOccurs) return 1; + const orgA = originalOrder.get(a); + const orgB = originalOrder.get(b); + return orgB - orgA; + }); + } + ); + compilation.hooks.optimizeChunkOrder.tap( + "OccurrenceOrderPlugin", + chunks => { + const occursInInitialChunksMap = new Map(); + const originalOrder = new Map(); + + let i = 0; + for (const c of chunks) { + let occurs = 0; + for (const chunkGroup of c.groupsIterable) { + for (const parent of chunkGroup.parentsIterable) { + if (parent.isInitial()) occurs++; + } + } + occursInInitialChunksMap.set(c, occurs); + originalOrder.set(c, i++); + } + + chunks.sort((a, b) => { + const aEntryOccurs = occursInInitialChunksMap.get(a); + const bEntryOccurs = occursInInitialChunksMap.get(b); + if (aEntryOccurs > bEntryOccurs) return -1; + if (aEntryOccurs < bEntryOccurs) return 1; + const aOccurs = a.getNumberOfGroups(); + const bOccurs = b.getNumberOfGroups(); + if (aOccurs > bOccurs) return -1; + if (aOccurs < bOccurs) return 1; + const orgA = originalOrder.get(a); + const orgB = originalOrder.get(b); + return orgB - orgA; + }); + } + ); }); } } diff --git a/lib/optimize/RemoveEmptyChunksPlugin.js b/lib/optimize/RemoveEmptyChunksPlugin.js index 430618e93..6a77e5278 100644 --- a/lib/optimize/RemoveEmptyChunksPlugin.js +++ b/lib/optimize/RemoveEmptyChunksPlugin.js @@ -6,16 +6,26 @@ class RemoveEmptyChunksPlugin { apply(compiler) { - compiler.hooks.compilation.tap("RemoveEmptyChunksPlugin", (compilation) => { - const handler = (chunks) => { - chunks.filter((chunk) => chunk.isEmpty() && !chunk.hasRuntime() && !chunk.hasEntryModule()) - .forEach((chunk) => { + compiler.hooks.compilation.tap("RemoveEmptyChunksPlugin", compilation => { + const handler = chunks => { + chunks + .filter( + chunk => + chunk.isEmpty() && !chunk.hasRuntime() && !chunk.hasEntryModule() + ) + .forEach(chunk => { chunk.remove("empty"); chunks.splice(chunks.indexOf(chunk), 1); }); }; - compilation.hooks.optimizeChunksBasic.tap("RemoveEmptyChunksPlugin", handler); - compilation.hooks.optimizeExtractedChunksBasic.tap("RemoveEmptyChunksPlugin", handler); + compilation.hooks.optimizeChunksBasic.tap( + "RemoveEmptyChunksPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "RemoveEmptyChunksPlugin", + handler + ); }); } } diff --git a/lib/optimize/RemoveParentModulesPlugin.js b/lib/optimize/RemoveParentModulesPlugin.js index b52f68340..1317349c5 100644 --- a/lib/optimize/RemoveParentModulesPlugin.js +++ b/lib/optimize/RemoveParentModulesPlugin.js @@ -11,11 +11,11 @@ const getParentChunksWithModule = (currentChunk, module) => { const chunks = []; const stack = new Set(currentChunk.parentsIterable); - for(const chunk of stack) { - if(chunk.containsModule(module)) { + for (const chunk of stack) { + if (chunk.containsModule(module)) { chunks.push(chunk); } else { - for(const parent of chunk.parentsIterable) { + for (const parent of chunk.parentsIterable) { stack.add(parent); } } @@ -26,38 +26,40 @@ const getParentChunksWithModule = (currentChunk, module) => { class RemoveParentModulesPlugin { apply(compiler) { - compiler.hooks.compilation.tap("RemoveParentModulesPlugin", (compilation) => { + compiler.hooks.compilation.tap("RemoveParentModulesPlugin", compilation => { const handler = (chunks, chunkGroups) => { const queue = new Queue(); const availableModulesMap = new Map(); - for(const chunkGroup of compilation.entrypoints.values()) { + for (const chunkGroup of compilation.entrypoints.values()) { // initialize available modules for chunks without parents availableModulesMap.set(chunkGroup, new Set()); - for(const child of chunkGroup.childrenIterable) - queue.enqueue(child); + for (const child of chunkGroup.childrenIterable) queue.enqueue(child); } - while(queue.length > 0) { + while (queue.length > 0) { const chunkGroup = queue.dequeue(); let availableModules = availableModulesMap.get(chunkGroup); let changed = false; - for(const parent of chunkGroup.parentsIterable) { + for (const parent of chunkGroup.parentsIterable) { const availableModulesInParent = availableModulesMap.get(parent); - if(availableModulesInParent !== undefined) { + if (availableModulesInParent !== undefined) { // If we know the available modules in parent: process these - if(availableModules === undefined) { + if (availableModules === undefined) { // if we have not own info yet: create new entry availableModules = new Set(availableModulesInParent); - for(const chunk of parent.chunks) { - for(const m of chunk.modulesIterable) + for (const chunk of parent.chunks) { + for (const m of chunk.modulesIterable) availableModules.add(m); } availableModulesMap.set(chunkGroup, availableModules); changed = true; } else { - for(const m of availableModules) { - if(!parent.containsModule(m) && !availableModulesInParent.has(m)) { + for (const m of availableModules) { + if ( + !parent.containsModule(m) && + !availableModulesInParent.has(m) + ) { availableModules.delete(m); changed = true; } @@ -65,37 +67,47 @@ class RemoveParentModulesPlugin { } } } - if(changed) { + if (changed) { // if something changed: enqueue our children - for(const child of chunkGroup.childrenIterable) + for (const child of chunkGroup.childrenIterable) queue.enqueue(child); } } // now we have available modules for every chunk - for(const chunk of chunks) { - const availableModulesSets = Array.from(chunk.groupsIterable, chunkGroup => availableModulesMap.get(chunkGroup)); - if(availableModulesSets.some(s => s === undefined)) continue; // No info about this chunk group + for (const chunk of chunks) { + const availableModulesSets = Array.from( + chunk.groupsIterable, + chunkGroup => availableModulesMap.get(chunkGroup) + ); + if (availableModulesSets.some(s => s === undefined)) continue; // No info about this chunk group const availableModules = intersect(availableModulesSets); const numberOfModules = chunk.getNumberOfModules(); const toRemove = new Set(); - if(numberOfModules < availableModules.size) { - for(const m of chunk.modulesIterable) - if(availableModules.has(m)) - toRemove.add(m); + if (numberOfModules < availableModules.size) { + for (const m of chunk.modulesIterable) + if (availableModules.has(m)) toRemove.add(m); } else { - for(const m of availableModules) - if(chunk.containsModule(m)) - toRemove.add(m); + for (const m of availableModules) + if (chunk.containsModule(m)) toRemove.add(m); } - for(const module of toRemove) { - module.rewriteChunkInReasons(chunk, getParentChunksWithModule(chunk, module)); + for (const module of toRemove) { + module.rewriteChunkInReasons( + chunk, + getParentChunksWithModule(chunk, module) + ); chunk.removeModule(module); } } }; - compilation.hooks.optimizeChunksBasic.tap("RemoveParentModulesPlugin", handler); - compilation.hooks.optimizeExtractedChunksBasic.tap("RemoveParentModulesPlugin", handler); + compilation.hooks.optimizeChunksBasic.tap( + "RemoveParentModulesPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "RemoveParentModulesPlugin", + handler + ); }); } } diff --git a/lib/optimize/RuntimeChunkPlugin.js b/lib/optimize/RuntimeChunkPlugin.js index 0aa1cd07f..9d503a67e 100644 --- a/lib/optimize/RuntimeChunkPlugin.js +++ b/lib/optimize/RuntimeChunkPlugin.js @@ -6,19 +6,22 @@ module.exports = class RuntimeChunkPlugin { constructor(options) { - this.options = Object.assign({ - name: entrypoint => `runtime~${entrypoint.name}` - }, options); + this.options = Object.assign( + { + name: entrypoint => `runtime~${entrypoint.name}` + }, + options + ); } apply(compiler) { compiler.hooks.thisCompilation.tap("RuntimeChunkPlugin", compilation => { compilation.hooks.optimizeChunksAdvanced.tap("RuntimeChunkPlugin", () => { - for(const entrypoint of compilation.entrypoints.values()) { + for (const entrypoint of compilation.entrypoints.values()) { const chunk = entrypoint.getRuntimeChunk(); - if(chunk.getNumberOfModules() > 0) { + if (chunk.getNumberOfModules() > 0) { let name = this.options.name; - if(typeof name === "function") { + if (typeof name === "function") { name = name(entrypoint); } const newChunk = compilation.addChunk(name); diff --git a/lib/optimize/SideEffectsFlagPlugin.js b/lib/optimize/SideEffectsFlagPlugin.js index a060ec874..e503262a6 100644 --- a/lib/optimize/SideEffectsFlagPlugin.js +++ b/lib/optimize/SideEffectsFlagPlugin.js @@ -11,13 +11,20 @@ const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportS class SideEffectsFlagPlugin { apply(compiler) { - compiler.hooks.normalModuleFactory.tap("SideEffectsFlagPlugin", (nmf) => { + compiler.hooks.normalModuleFactory.tap("SideEffectsFlagPlugin", nmf => { nmf.hooks.module.tap("SideEffectsFlagPlugin", (module, data) => { const resolveData = data.resourceResolveData; - if(resolveData && resolveData.descriptionFileData && resolveData.relativePath) { + if ( + resolveData && + resolveData.descriptionFileData && + resolveData.relativePath + ) { const sideEffects = resolveData.descriptionFileData.sideEffects; - const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects(resolveData.relativePath, sideEffects); - if(!hasSideEffects) { + const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects( + resolveData.relativePath, + sideEffects + ); + if (!hasSideEffects) { module.factoryMeta.sideEffectFree = true; } } @@ -25,115 +32,124 @@ class SideEffectsFlagPlugin { return module; }); nmf.hooks.module.tap("SideEffectsFlagPlugin", (module, data) => { - if(data.settings.sideEffects === false) + if (data.settings.sideEffects === false) module.factoryMeta.sideEffectFree = true; - else if(data.settings.sideEffects === true) + else if (data.settings.sideEffects === true) module.factoryMeta.sideEffectFree = false; }); }); - compiler.hooks.compilation.tap("SideEffectsFlagPlugin", (compilation) => { - compilation.hooks.optimizeDependencies.tap("SideEffectsFlagPlugin", (modules) => { - const reexportMaps = new Map(); + compiler.hooks.compilation.tap("SideEffectsFlagPlugin", compilation => { + compilation.hooks.optimizeDependencies.tap( + "SideEffectsFlagPlugin", + modules => { + const reexportMaps = new Map(); - // Capture reexports of sideEffectFree modules - for(const module of modules) { - const removeDependencies = []; - for(const dep of module.dependencies) { - if(dep instanceof HarmonyImportSideEffectDependency) { - if(dep.module && dep.module.factoryMeta.sideEffectFree) { - removeDependencies.push(dep); - } - } else if(dep instanceof HarmonyExportImportedSpecifierDependency) { - if(module.factoryMeta.sideEffectFree) { - const mode = dep.getMode(true); - if(mode.type === "safe-reexport") { - let map = reexportMaps.get(module); - if(!map) { - reexportMaps.set(module, map = new Map()); - } - for(const pair of mode.map) { - map.set(pair[0], { - module: mode.module, - exportName: pair[1] - }); + // Capture reexports of sideEffectFree modules + for (const module of modules) { + const removeDependencies = []; + for (const dep of module.dependencies) { + if (dep instanceof HarmonyImportSideEffectDependency) { + if (dep.module && dep.module.factoryMeta.sideEffectFree) { + removeDependencies.push(dep); + } + } else if ( + dep instanceof HarmonyExportImportedSpecifierDependency + ) { + if (module.factoryMeta.sideEffectFree) { + const mode = dep.getMode(true); + if (mode.type === "safe-reexport") { + let map = reexportMaps.get(module); + if (!map) { + reexportMaps.set(module, (map = new Map())); + } + for (const pair of mode.map) { + map.set(pair[0], { + module: mode.module, + exportName: pair[1] + }); + } } } } } - } - for(const dep of removeDependencies) { - module.removeDependency(dep); - dep.module.reasons = dep.module.reasons.filter(r => r.dependency !== dep); - } - } - - // Flatten reexports - for(const map of reexportMaps.values()) { - for(const pair of map) { - let mapping = pair[1]; - while(mapping) { - const innerMap = reexportMaps.get(mapping.module); - if(!innerMap) break; - const newMapping = innerMap.get(mapping.exportName); - if(newMapping) { - map.set(pair[0], newMapping); - } - mapping = newMapping; + for (const dep of removeDependencies) { + module.removeDependency(dep); + dep.module.reasons = dep.module.reasons.filter( + r => r.dependency !== dep + ); } } - } - // Update imports along the reexports from sideEffectFree modules - const updates = []; - for(const pair of reexportMaps) { - const module = pair[0]; - const map = pair[1]; - for(const reason of module.reasons) { - const dep = reason.dependency; - if(dep instanceof HarmonyImportSpecifierDependency) { - const mapping = map.get(dep.id); - if(mapping) { - updates.push({ - dep, - mapping, - module, - reason - }); + // Flatten reexports + for (const map of reexportMaps.values()) { + for (const pair of map) { + let mapping = pair[1]; + while (mapping) { + const innerMap = reexportMaps.get(mapping.module); + if (!innerMap) break; + const newMapping = innerMap.get(mapping.exportName); + if (newMapping) { + map.set(pair[0], newMapping); + } + mapping = newMapping; } } } - } - // Execute updates - for(const update of updates) { - const dep = update.dep; - const mapping = update.mapping; - const module = update.module; - const reason = update.reason; - dep.module = mapping.module; - dep.id = mapping.exportName; - module.removeReason(reason.module, dep); - mapping.module.addReason(reason.module, dep); + // Update imports along the reexports from sideEffectFree modules + const updates = []; + for (const pair of reexportMaps) { + const module = pair[0]; + const map = pair[1]; + for (const reason of module.reasons) { + const dep = reason.dependency; + if (dep instanceof HarmonyImportSpecifierDependency) { + const mapping = map.get(dep.id); + if (mapping) { + updates.push({ + dep, + mapping, + module, + reason + }); + } + } + } + } + + // Execute updates + for (const update of updates) { + const dep = update.dep; + const mapping = update.mapping; + const module = update.module; + const reason = update.reason; + dep.module = mapping.module; + dep.id = mapping.exportName; + module.removeReason(reason.module, dep); + mapping.module.addReason(reason.module, dep); + } } - }); + ); }); } static moduleHasSideEffects(moduleName, flagValue) { - switch(typeof flagValue) { + switch (typeof flagValue) { case "undefined": return true; case "boolean": return flagValue; case "string": - if(process.platform === "win32") { + if (process.platform === "win32") { flagValue = flagValue.replace(/\\/g, "/"); } return mm.isMatch(moduleName, flagValue, { matchBase: true }); case "object": - return flagValue.some(glob => SideEffectsFlagPlugin.moduleHasSideEffects(moduleName, glob)); + return flagValue.some(glob => + SideEffectsFlagPlugin.moduleHasSideEffects(moduleName, glob) + ); } } } diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 74c2d8432..fb8dc116c 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -9,19 +9,23 @@ const SortableSet = require("../util/SortableSet"); const GraphHelpers = require("../GraphHelpers"); const isSubset = require("../util/SetHelpers").isSubset; -const hashFilename = (name) => { - return crypto.createHash("md4").update(name).digest("hex").slice(0, 8); +const hashFilename = name => { + return crypto + .createHash("md4") + .update(name) + .digest("hex") + .slice(0, 8); }; const sortByIdentifier = (a, b) => { - if(a.identifier() > b.identifier()) return 1; - if(a.identifier() < b.identifier()) return -1; + if (a.identifier() > b.identifier()) return 1; + if (a.identifier() < b.identifier()) return -1; return 0; }; const getRequests = chunk => { let requests = 0; - for(const chunkGroup of chunk.groupsIterable) { + for (const chunkGroup of chunk.groupsIterable) { requests = Math.max(requests, chunkGroup.chunks.length); } return requests; @@ -29,14 +33,13 @@ const getRequests = chunk => { const getModulesSize = modules => { let sum = 0; - for(const m of modules) - sum += m.size(); + for (const m of modules) sum += m.size(); return sum; }; const isOverlap = (a, b) => { - for(const item of a.keys()) { - if(b.has(item)) return true; + for (const item of a.keys()) { + if (b.has(item)) return true; } return false; }; @@ -44,33 +47,34 @@ const isOverlap = (a, b) => { const compareEntries = (a, b) => { // 1. by priority const diffPriority = a.cacheGroup.priority - b.cacheGroup.priority; - if(diffPriority) return diffPriority; + if (diffPriority) return diffPriority; // 2. by number of chunks const diffCount = a.chunks.size - b.chunks.size; - if(diffCount) return diffCount; + if (diffCount) return diffCount; // 3. by size reduction const aSizeReduce = a.size * (a.chunks.size - 1); const bSizeReduce = b.size * (b.chunks.size - 1); const diffSizeReduce = aSizeReduce - bSizeReduce; - if(diffSizeReduce) return diffSizeReduce; + if (diffSizeReduce) return diffSizeReduce; // 4. by number of modules (to be able to compare by identifier) const modulesA = a.modules; const modulesB = b.modules; const diff = modulesA.size - modulesB.size; - if(diff) return diff; + if (diff) return diff; // 5. by module identifiers modulesA.sort(); modulesB.sort(); const aI = modulesA[Symbol.iterator](); const bI = modulesB[Symbol.iterator](); - while(true) { // eslint-disable-line + while (true) { + // eslint-disable-line const aItem = aI.next(); const bItem = bI.next(); - if(aItem.done) return 0; + if (aItem.done) return 0; const aModuleIdentifier = aItem.value.identifier(); const bModuleIdentifier = bItem.value.identifier(); - if(aModuleIdentifier > bModuleIdentifier) return -1; - if(aModuleIdentifier < bModuleIdentifier) return 1; + if (aModuleIdentifier > bModuleIdentifier) return -1; + if (aModuleIdentifier < bModuleIdentifier) return 1; } }; @@ -87,69 +91,74 @@ module.exports = class SplitChunksPlugin { maxAsyncRequests: options.maxAsyncRequests || 1, maxInitialRequests: options.maxInitialRequests || 1, getName: SplitChunksPlugin.normalizeName(options.name) || (() => {}), - getCacheGroups: SplitChunksPlugin.normalizeCacheGroups(options.cacheGroups), + getCacheGroups: SplitChunksPlugin.normalizeCacheGroups( + options.cacheGroups + ) }; } static normalizeName(option) { - if(option === true) { + if (option === true) { const fn = (module, chunks, cacheGroup) => { const names = chunks.map(c => c.name); - if(!names.every(Boolean)) return; + if (!names.every(Boolean)) return; names.sort(); - let name = (cacheGroup && cacheGroup !== "default" ? cacheGroup + "~" : "") + names.join("~"); + let name = + (cacheGroup && cacheGroup !== "default" ? cacheGroup + "~" : "") + + names.join("~"); // Filenames and paths can't be too long otherwise an // ENAMETOOLONG error is raised. If the generated name if too // long, it is truncated and a hash is appended. The limit has // been set to 100 to prevent `[name].[chunkhash].[ext]` from // generating a 256+ character string. - if(name.length > 100) { + if (name.length > 100) { name = name.slice(0, 100) + "~" + hashFilename(name); } return name; }; return fn; } - if(typeof option === "string") { + if (typeof option === "string") { const fn = () => { return option; }; return fn; } - if(typeof option === "function") - return option; + if (typeof option === "function") return option; } static normalizeCacheGroups(cacheGroups) { - if(typeof cacheGroups === "function") { + if (typeof cacheGroups === "function") { return cacheGroups; } - if(cacheGroups && typeof cacheGroups === "object") { + if (cacheGroups && typeof cacheGroups === "object") { const fn = (module, chunks) => { let results; - for(const key of Object.keys(cacheGroups)) { + for (const key of Object.keys(cacheGroups)) { let option = cacheGroups[key]; - if(option === false) - continue; - if(option instanceof RegExp || typeof option === "string") { + if (option === false) continue; + if (option instanceof RegExp || typeof option === "string") { option = { test: option }; } - if(typeof option === "function") { + if (typeof option === "function") { let result = option(module); - if(result) { - if(results === undefined) results = []; - for(const r of (Array.isArray(result) ? result : [result])) { - const result = Object.assign({ - key, - }, r); - if(result.name) result.getName = () => result.name; + if (result) { + if (results === undefined) results = []; + for (const r of Array.isArray(result) ? result : [result]) { + const result = Object.assign( + { + key + }, + r + ); + if (result.name) result.getName = () => result.name; results.push(result); } } - } else if(SplitChunksPlugin.checkTest(option.test, module, chunks)) { - if(results === undefined) results = []; + } else if (SplitChunksPlugin.checkTest(option.test, module, chunks)) { + if (results === undefined) results = []; results.push({ key: key, priority: option.priority, @@ -173,23 +182,19 @@ module.exports = class SplitChunksPlugin { } static checkTest(test, module, chunks) { - if(test === undefined) - return true; - if(typeof test === "function") - return test(module, chunks); - if(typeof test === "boolean") - return test; - const names = chunks.map(c => c.name).concat(module.nameForCondition ? [module.nameForCondition()] : []).filter(Boolean); - if(typeof test === "string") { - for(const name of names) - if(name.startsWith(test)) - return true; + if (test === undefined) return true; + if (typeof test === "function") return test(module, chunks); + if (typeof test === "boolean") return test; + const names = chunks + .map(c => c.name) + .concat(module.nameForCondition ? [module.nameForCondition()] : []) + .filter(Boolean); + if (typeof test === "string") { + for (const name of names) if (name.startsWith(test)) return true; return false; } - if(test instanceof RegExp) { - for(const name of names) - if(test.test(name)) - return true; + if (test instanceof RegExp) { + for (const name of names) if (test.test(name)) return true; return false; } return false; @@ -201,213 +206,269 @@ module.exports = class SplitChunksPlugin { compilation.hooks.unseal.tap("SplitChunksPlugin", () => { alreadyOptimized = false; }); - compilation.hooks.optimizeChunksAdvanced.tap("SplitChunksPlugin", chunks => { - if(alreadyOptimized) return; - alreadyOptimized = true; - // Give each selected chunk an index (to create strings from chunks) - const indexMap = new Map(); - let index = 1; - for(const chunk of chunks) { - indexMap.set(chunk, index++); - } - const getKey = chunks => { - return Array.from(chunks, c => indexMap.get(c)).sort().join(); - }; - // Create a list of possible combinations - const chunkSetsInGraph = new Map(); // Map> - for(const module of compilation.modules) { - const chunkIndices = getKey(module.chunksIterable); - chunkSetsInGraph.set(chunkIndices, new Set(module.chunksIterable)); - } - const combinations = new Map(); // Map[]> - for(const [key, chunksSet] of chunkSetsInGraph) { - var array = []; - for(const set of chunkSetsInGraph.values()) { - if(isSubset(chunksSet, set)) { - array.push(set); + compilation.hooks.optimizeChunksAdvanced.tap( + "SplitChunksPlugin", + chunks => { + if (alreadyOptimized) return; + alreadyOptimized = true; + // Give each selected chunk an index (to create strings from chunks) + const indexMap = new Map(); + let index = 1; + for (const chunk of chunks) { + indexMap.set(chunk, index++); + } + const getKey = chunks => { + return Array.from(chunks, c => indexMap.get(c)) + .sort() + .join(); + }; + // Create a list of possible combinations + const chunkSetsInGraph = new Map(); // Map> + for (const module of compilation.modules) { + const chunkIndices = getKey(module.chunksIterable); + chunkSetsInGraph.set(chunkIndices, new Set(module.chunksIterable)); + } + const combinations = new Map(); // Map[]> + for (const [key, chunksSet] of chunkSetsInGraph) { + var array = []; + for (const set of chunkSetsInGraph.values()) { + if (isSubset(chunksSet, set)) { + array.push(set); + } + } + combinations.set(key, array); + } + // Map a list of chunks to a list of modules + // For the key the chunk "index" is used, the value is a SortableSet of modules + const chunksInfoMap = new Map(); + // Walk through all modules + for (const module of compilation.modules) { + // Get array of chunks + const chunks = module.getChunks(); + // Get cache group + let cacheGroups = this.options.getCacheGroups(module, chunks); + if (!Array.isArray(cacheGroups)) continue; + for (const cacheGroupSource of cacheGroups) { + const cacheGroup = { + key: cacheGroupSource.key, + priority: cacheGroupSource.priority || 0, + chunks: cacheGroupSource.chunks || this.options.chunks, + minSize: + cacheGroupSource.minSize !== undefined + ? cacheGroupSource.minSize + : cacheGroupSource.enforce ? 0 : this.options.minSize, + minChunks: + cacheGroupSource.minChunks !== undefined + ? cacheGroupSource.minChunks + : cacheGroupSource.enforce ? 1 : this.options.minChunks, + maxAsyncRequests: + cacheGroupSource.maxAsyncRequests !== undefined + ? cacheGroupSource.maxAsyncRequests + : cacheGroupSource.enforce + ? Infinity + : this.options.maxAsyncRequests, + maxInitialRequests: + cacheGroupSource.maxInitialRequests !== undefined + ? cacheGroupSource.maxInitialRequests + : cacheGroupSource.enforce + ? Infinity + : this.options.maxInitialRequests, + getName: + cacheGroupSource.getName !== undefined + ? cacheGroupSource.getName + : this.options.getName, + reuseExistingChunk: cacheGroupSource.reuseExistingChunk + }; + // For all combination of chunk selection + for (const chunkCombination of combinations.get(getKey(chunks))) { + // Get indices of chunks in which this module occurs + const chunkIndices = Array.from(chunkCombination, chunk => + indexMap.get(chunk) + ); + // Break if minimum number of chunks is not reached + if (chunkIndices.length < cacheGroup.minChunks) continue; + // Select chunks by configuration + const selectedChunks = + cacheGroup.chunks === "initial" + ? Array.from(chunkCombination).filter(chunk => + chunk.canBeInitial() + ) + : cacheGroup.chunks === "async" + ? Array.from(chunkCombination).filter( + chunk => !chunk.canBeInitial() + ) + : Array.from(chunkCombination); + // Determine name for split chunk + const name = cacheGroup.getName( + module, + selectedChunks, + cacheGroup.key + ); + // Create key for maps + // When it has a name we use the name as key + // Elsewise we create the key from chunks and cache group key + // This automatically merges equal names + const chunksKey = getKey(selectedChunks); + const key = + (name && `name:${name}`) || + `chunks:${chunksKey} key:${cacheGroup.key}`; + // Add module to maps + let info = chunksInfoMap.get(key); + if (info === undefined) { + chunksInfoMap.set( + key, + (info = { + modules: new SortableSet(undefined, sortByIdentifier), + cacheGroup, + name, + chunks: new Map(), + reusedableChunks: new Set(), + chunksKeys: new Set() + }) + ); + } + info.modules.add(module); + if (!info.chunksKeys.has(chunksKey)) { + info.chunksKeys.add(chunksKey); + for (const chunk of selectedChunks) { + info.chunks.set(chunk, chunk.getNumberOfModules()); + } + } + } } } - combinations.set(key, array); - } - // Map a list of chunks to a list of modules - // For the key the chunk "index" is used, the value is a SortableSet of modules - const chunksInfoMap = new Map(); - // Walk through all modules - for(const module of compilation.modules) { - // Get array of chunks - const chunks = module.getChunks(); - // Get cache group - let cacheGroups = this.options.getCacheGroups(module, chunks); - if(!Array.isArray(cacheGroups)) continue; - for(const cacheGroupSource of cacheGroups) { - const cacheGroup = { - key: cacheGroupSource.key, - priority: cacheGroupSource.priority || 0, - chunks: cacheGroupSource.chunks || this.options.chunks, - minSize: cacheGroupSource.minSize !== undefined ? cacheGroupSource.minSize : cacheGroupSource.enforce ? 0 : this.options.minSize, - minChunks: cacheGroupSource.minChunks !== undefined ? cacheGroupSource.minChunks : cacheGroupSource.enforce ? 1 : this.options.minChunks, - maxAsyncRequests: cacheGroupSource.maxAsyncRequests !== undefined ? cacheGroupSource.maxAsyncRequests : cacheGroupSource.enforce ? Infinity : this.options.maxAsyncRequests, - maxInitialRequests: cacheGroupSource.maxInitialRequests !== undefined ? cacheGroupSource.maxInitialRequests : cacheGroupSource.enforce ? Infinity : this.options.maxInitialRequests, - getName: cacheGroupSource.getName !== undefined ? cacheGroupSource.getName : this.options.getName, - reuseExistingChunk: cacheGroupSource.reuseExistingChunk - }; - // For all combination of chunk selection - for(const chunkCombination of combinations.get(getKey(chunks))) { - // Get indices of chunks in which this module occurs - const chunkIndices = Array.from(chunkCombination, chunk => indexMap.get(chunk)); - // Break if minimum number of chunks is not reached - if(chunkIndices.length < cacheGroup.minChunks) + for (const [key, info] of chunksInfoMap) { + // Get size of module lists + info.size = getModulesSize(info.modules); + if (info.size < info.cacheGroup.minSize) { + chunksInfoMap.delete(key); + } + } + let changed = false; + while (chunksInfoMap.size > 0) { + // Find best matching entry + let bestEntryKey; + let bestEntry; + for (const pair of chunksInfoMap) { + const key = pair[0]; + const info = pair[1]; + if (bestEntry === undefined) { + bestEntry = info; + bestEntryKey = key; + } else if (compareEntries(bestEntry, info) < 0) { + bestEntry = info; + bestEntryKey = key; + } + } + + const item = bestEntry; + chunksInfoMap.delete(bestEntryKey); + + let chunkName = item.name; + // Variable for the new chunk (lazy created) + let newChunk; + // When no chunk name, check if we can reuse a chunk instead of creating a new one + let isReused = false; + if (item.cacheGroup.reuseExistingChunk) { + for (const pair of item.chunks) { + if (pair[1] === item.modules.size) { + const chunk = pair[0]; + if (chunk.hasEntryModule()) continue; + if (!newChunk || !newChunk.name) newChunk = chunk; + else if ( + chunk.name && + chunk.name.length < newChunk.name.length + ) + newChunk = chunk; + else if ( + chunk.name && + chunk.name.length === newChunk.name.length && + chunk.name < newChunk.name + ) + newChunk = chunk; + chunkName = undefined; + isReused = true; + } + } + } + // Walk through all chunks + for (const chunk of item.chunks.keys()) { + // skip if we address ourself + if (chunk.name === chunkName || chunk === newChunk) continue; + // respect max requests when not enforced + const maxRequests = chunk.isOnlyInitial() + ? item.cacheGroup.maxInitialRequests + : chunk.canBeInitial() + ? Math.min( + item.cacheGroup.maxInitialRequests, + item.cacheGroup.maxAsyncRequests + ) + : item.cacheGroup.maxAsyncRequests; + if (isFinite(maxRequests) && getRequests(chunk) >= maxRequests) continue; - // Select chunks by configuration - const selectedChunks = cacheGroup.chunks === "initial" ? Array.from(chunkCombination).filter(chunk => chunk.canBeInitial()) : - cacheGroup.chunks === "async" ? Array.from(chunkCombination).filter(chunk => !chunk.canBeInitial()) : - Array.from(chunkCombination); - // Determine name for split chunk - const name = cacheGroup.getName(module, selectedChunks, cacheGroup.key); - // Create key for maps - // When it has a name we use the name as key - // Elsewise we create the key from chunks and cache group key - // This automatically merges equal names - const chunksKey = getKey(selectedChunks); - const key = name && `name:${name}` || - `chunks:${chunksKey} key:${cacheGroup.key}`; - // Add module to maps - let info = chunksInfoMap.get(key); - if(info === undefined) { - chunksInfoMap.set(key, info = { - modules: new SortableSet(undefined, sortByIdentifier), - cacheGroup, - name, - chunks: new Map(), - reusedableChunks: new Set(), - chunksKeys: new Set() - }); + if (newChunk === undefined) { + // Create the new chunk + newChunk = compilation.addChunk(chunkName); } - info.modules.add(module); - if(!info.chunksKeys.has(chunksKey)) { - info.chunksKeys.add(chunksKey); - for(const chunk of selectedChunks) { - info.chunks.set(chunk, chunk.getNumberOfModules()); + // Add graph connections for splitted chunk + chunk.split(newChunk); + // Remove all selected modules from the chunk + for (const module of item.modules) { + chunk.removeModule(module); + module.rewriteChunkInReasons(chunk, [newChunk]); + } + } + // If we successfully created a new chunk or reused one + if (newChunk) { + // Add a note to the chunk + newChunk.chunkReason = isReused + ? "reused as split chunk" + : "split chunk"; + if (item.cacheGroup.key) { + newChunk.chunkReason += ` (cache group: ${ + item.cacheGroup.key + })`; + } + if (chunkName) { + newChunk.chunkReason += ` (name: ${chunkName})`; + // If the choosen name is already an entry point we remove the entry point + const entrypoint = compilation.entrypoints.get(chunkName); + if (entrypoint) { + compilation.entrypoints.delete(chunkName); + entrypoint.remove(); + newChunk.entryModule = undefined; } } - } - } - } - for(const [key, info] of chunksInfoMap) { - // Get size of module lists - info.size = getModulesSize(info.modules); - if(info.size < info.cacheGroup.minSize) { - chunksInfoMap.delete(key); - } - } - let changed = false; - while(chunksInfoMap.size > 0) { - // Find best matching entry - let bestEntryKey; - let bestEntry; - for(const pair of chunksInfoMap) { - const key = pair[0]; - const info = pair[1]; - if(bestEntry === undefined) { - bestEntry = info; - bestEntryKey = key; - } else if(compareEntries(bestEntry, info) < 0) { - bestEntry = info; - bestEntryKey = key; - } - } - - const item = bestEntry; - chunksInfoMap.delete(bestEntryKey); - - let chunkName = item.name; - // Variable for the new chunk (lazy created) - let newChunk; - // When no chunk name, check if we can reuse a chunk instead of creating a new one - let isReused = false; - if(item.cacheGroup.reuseExistingChunk) { - for(const pair of item.chunks) { - if(pair[1] === item.modules.size) { - const chunk = pair[0]; - if(chunk.hasEntryModule()) continue; - if(!newChunk || !newChunk.name) - newChunk = chunk; - else if(chunk.name && chunk.name.length < newChunk.name.length) - newChunk = chunk; - else if(chunk.name && chunk.name.length === newChunk.name.length && chunk.name < newChunk.name) - newChunk = chunk; - chunkName = undefined; - isReused = true; - } - } - } - // Walk through all chunks - for(const chunk of item.chunks.keys()) { - // skip if we address ourself - if(chunk.name === chunkName || chunk === newChunk) continue; - // respect max requests when not enforced - const maxRequests = chunk.isOnlyInitial() ? item.cacheGroup.maxInitialRequests : - chunk.canBeInitial() ? Math.min(item.cacheGroup.maxInitialRequests, item.cacheGroup.maxAsyncRequests) : - item.cacheGroup.maxAsyncRequests; - if(isFinite(maxRequests) && getRequests(chunk) >= maxRequests) continue; - if(newChunk === undefined) { - // Create the new chunk - newChunk = compilation.addChunk(chunkName); - } - // Add graph connections for splitted chunk - chunk.split(newChunk); - // Remove all selected modules from the chunk - for(const module of item.modules) { - chunk.removeModule(module); - module.rewriteChunkInReasons(chunk, [newChunk]); - } - } - // If we successfully created a new chunk or reused one - if(newChunk) { - // Add a note to the chunk - newChunk.chunkReason = isReused ? "reused as split chunk" : "split chunk"; - if(item.cacheGroup.key) { - newChunk.chunkReason += ` (cache group: ${item.cacheGroup.key})`; - } - if(chunkName) { - newChunk.chunkReason += ` (name: ${chunkName})`; - // If the choosen name is already an entry point we remove the entry point - const entrypoint = compilation.entrypoints.get(chunkName); - if(entrypoint) { - compilation.entrypoints.delete(chunkName); - entrypoint.remove(); - newChunk.entryModule = undefined; - } - } - if(!isReused) { - // Add all modules to the new chunk - for(const module of item.modules) { - GraphHelpers.connectChunkAndModule(newChunk, module); - } - } - // remove all modules from other entries and update size - for(const [key, info] of chunksInfoMap) { - if(isOverlap(info.chunks, item.chunks)) { - const oldSize = info.modules.size; - for(const module of item.modules) { - info.modules.delete(module); + if (!isReused) { + // Add all modules to the new chunk + for (const module of item.modules) { + GraphHelpers.connectChunkAndModule(newChunk, module); } - if(info.modules.size === 0) { - chunksInfoMap.delete(key); - continue; - } - if(info.modules.size !== oldSize) { - info.size = getModulesSize(info.modules); - if(info.size < info.cacheGroup.minSize) + } + // remove all modules from other entries and update size + for (const [key, info] of chunksInfoMap) { + if (isOverlap(info.chunks, item.chunks)) { + const oldSize = info.modules.size; + for (const module of item.modules) { + info.modules.delete(module); + } + if (info.modules.size === 0) { chunksInfoMap.delete(key); + continue; + } + if (info.modules.size !== oldSize) { + info.size = getModulesSize(info.modules); + if (info.size < info.cacheGroup.minSize) + chunksInfoMap.delete(key); + } } } + changed = true; } - changed = true; } + if (changed) return true; } - if(changed) return true; - }); + ); }); } }; diff --git a/lib/performance/AssetsOverSizeLimitWarning.js b/lib/performance/AssetsOverSizeLimitWarning.js index f1fb52cbb..55c0220cd 100644 --- a/lib/performance/AssetsOverSizeLimitWarning.js +++ b/lib/performance/AssetsOverSizeLimitWarning.js @@ -13,8 +13,15 @@ module.exports = class AssetsOverSizeLimitWarning extends WebpackError { this.name = "AssetsOverSizeLimitWarning"; this.assets = assetsOverSizeLimit; - const assetLists = this.assets.map(asset => `\n ${asset.name} (${SizeFormatHelpers.formatSize(asset.size)})`).join(""); - this.message = `asset size limit: The following asset(s) exceed the recommended size limit (${SizeFormatHelpers.formatSize(assetLimit)}). + const assetLists = this.assets + .map( + asset => + `\n ${asset.name} (${SizeFormatHelpers.formatSize(asset.size)})` + ) + .join(""); + this.message = `asset size limit: The following asset(s) exceed the recommended size limit (${SizeFormatHelpers.formatSize( + assetLimit + )}). This can impact web performance. Assets: ${assetLists}`; diff --git a/lib/performance/EntrypointsOverSizeLimitWarning.js b/lib/performance/EntrypointsOverSizeLimitWarning.js index e33b5ac2e..e81ea1e29 100644 --- a/lib/performance/EntrypointsOverSizeLimitWarning.js +++ b/lib/performance/EntrypointsOverSizeLimitWarning.js @@ -13,14 +13,17 @@ module.exports = class EntrypointsOverSizeLimitWarning extends WebpackError { this.name = "EntrypointsOverSizeLimitWarning"; this.entrypoints = entrypoints; - const entrypointList = this.entrypoints.map(entrypoint => `\n ${ - entrypoint.name - } (${ - SizeFormatHelpers.formatSize(entrypoint.size) - })\n${ - entrypoint.files.map(asset => ` ${asset}`).join("\n") - }`).join(""); - this.message = `entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (${SizeFormatHelpers.formatSize(entrypointLimit)}). This can impact web performance. + const entrypointList = this.entrypoints + .map( + entrypoint => + `\n ${entrypoint.name} (${SizeFormatHelpers.formatSize( + entrypoint.size + )})\n${entrypoint.files.map(asset => ` ${asset}`).join("\n")}` + ) + .join(""); + this.message = `entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (${SizeFormatHelpers.formatSize( + entrypointLimit + )}). This can impact web performance. Entrypoints:${entrypointList}\n`; Error.captureStackTrace(this, this.constructor); diff --git a/lib/performance/NoAsyncChunksWarning.js b/lib/performance/NoAsyncChunksWarning.js index dc456f687..9687d5056 100644 --- a/lib/performance/NoAsyncChunksWarning.js +++ b/lib/performance/NoAsyncChunksWarning.js @@ -11,7 +11,8 @@ module.exports = class NoAsyncChunksWarning extends WebpackError { super(); this.name = "NoAsyncChunksWarning"; - this.message = "webpack performance recommendations: \n" + + this.message = + "webpack performance recommendations: \n" + "You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.\n" + "For more info visit https://webpack.js.org/guides/code-splitting/"; diff --git a/lib/performance/SizeLimitsPlugin.js b/lib/performance/SizeLimitsPlugin.js index 85d3c28ce..914fa7506 100644 --- a/lib/performance/SizeLimitsPlugin.js +++ b/lib/performance/SizeLimitsPlugin.js @@ -18,15 +18,14 @@ module.exports = class SizeLimitsPlugin { const entrypointSizeLimit = this.maxEntrypointSize; const assetSizeLimit = this.maxAssetSize; const hints = this.hints; - const assetFilter = this.assetFilter || (asset => !(asset.endsWith(".map"))); + const assetFilter = this.assetFilter || (asset => !asset.endsWith(".map")); - compiler.hooks.afterEmit.tap("SizeLimitsPlugin", (compilation) => { + compiler.hooks.afterEmit.tap("SizeLimitsPlugin", compilation => { const warnings = []; const getEntrypointSize = entrypoint => - entrypoint.getFiles() - .reduce((currentSize, file) => { - if(assetFilter(file) && compilation.assets[file]) { + entrypoint.getFiles().reduce((currentSize, file) => { + if (assetFilter(file) && compilation.assets[file]) { return currentSize + compilation.assets[file].size(); } @@ -34,29 +33,29 @@ module.exports = class SizeLimitsPlugin { }, 0); const assetsOverSizeLimit = []; - for(const assetName of Object.keys(compilation.assets)) { - if(!assetFilter(assetName)) { + for (const assetName of Object.keys(compilation.assets)) { + if (!assetFilter(assetName)) { continue; } const asset = compilation.assets[assetName]; const size = asset.size(); - if(size > assetSizeLimit) { + if (size > assetSizeLimit) { assetsOverSizeLimit.push({ name: assetName, - size: size, + size: size }); asset.isOverSizeLimit = true; } } const entrypointsOverLimit = []; - for(const pair of compilation.entrypoints) { + for (const pair of compilation.entrypoints) { const name = pair[0]; const entry = pair[1]; const size = getEntrypointSize(entry, compilation); - if(size > entrypointSizeLimit) { + if (size > entrypointSizeLimit) { entrypointsOverLimit.push({ name: name, size: size, @@ -66,32 +65,35 @@ module.exports = class SizeLimitsPlugin { } } - if(hints) { + if (hints) { // 1. Individual Chunk: Size < 250kb // 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb // 3. No Async Chunks // if !1, then 2, if !2 return - if(assetsOverSizeLimit.length > 0) { + if (assetsOverSizeLimit.length > 0) { warnings.push( - new AssetsOverSizeLimitWarning( - assetsOverSizeLimit, - assetSizeLimit)); + new AssetsOverSizeLimitWarning(assetsOverSizeLimit, assetSizeLimit) + ); } - if(entrypointsOverLimit.length > 0) { + if (entrypointsOverLimit.length > 0) { warnings.push( new EntrypointsOverSizeLimitWarning( entrypointsOverLimit, - entrypointSizeLimit)); + entrypointSizeLimit + ) + ); } - if(warnings.length > 0) { - const hasAsyncChunks = compilation.chunks.filter(chunk => !chunk.canBeInitial()).length > 0; + if (warnings.length > 0) { + const hasAsyncChunks = + compilation.chunks.filter(chunk => !chunk.canBeInitial()).length > + 0; - if(!hasAsyncChunks) { + if (!hasAsyncChunks) { warnings.push(new NoAsyncChunksWarning()); } - if(hints === "error") { + if (hints === "error") { compilation.errors.push(...warnings); } else { compilation.warnings.push(...warnings); diff --git a/lib/prepareOptions.js b/lib/prepareOptions.js index 25686c016..8f1d1b17a 100644 --- a/lib/prepareOptions.js +++ b/lib/prepareOptions.js @@ -1,15 +1,16 @@ "use strict"; const handleExport = options => { - const isES6DefaultExported = ( - typeof options === "object" && options !== null && typeof options.default !== "undefined" - ); + const isES6DefaultExported = + typeof options === "object" && + options !== null && + typeof options.default !== "undefined"; options = isES6DefaultExported ? options.default : options; return options; }; const handleFunction = (options, argv) => { - if(typeof options === "function") { + if (typeof options === "function") { options = options(argv.env, argv); } return options; @@ -20,7 +21,7 @@ module.exports = (options, argv) => { options = handleExport(options); - if(Array.isArray(options)) { + if (Array.isArray(options)) { options = options.map(_options => handleFunction(_options, argv)); } else { options = handleFunction(options, argv); diff --git a/lib/util/Queue.js b/lib/util/Queue.js index 14b72223c..21e2925e8 100644 --- a/lib/util/Queue.js +++ b/lib/util/Queue.js @@ -16,7 +16,7 @@ module.exports = class Queue { dequeue() { const result = this.iterator.next(); - if(result.done) return undefined; + if (result.done) return undefined; this.set.delete(result.value); return result.value; } diff --git a/lib/util/Semaphore.js b/lib/util/Semaphore.js index c8cab0a45..177f94bd7 100644 --- a/lib/util/Semaphore.js +++ b/lib/util/Semaphore.js @@ -11,7 +11,7 @@ class Semaphore { } acquire(callback) { - if(this.available > 0) { + if (this.available > 0) { this.available--; callback(); } else { @@ -20,7 +20,7 @@ class Semaphore { } release() { - if(this.waiters.length > 0) { + if (this.waiters.length > 0) { const callback = this.waiters.pop(); process.nextTick(callback); } else { diff --git a/lib/util/SetHelpers.js b/lib/util/SetHelpers.js index d134a6fd2..e5395d870 100644 --- a/lib/util/SetHelpers.js +++ b/lib/util/SetHelpers.js @@ -1,23 +1,23 @@ "use strict"; exports.intersect = sets => { - if(sets.length === 0) return new Set(); - if(sets.length === 1) return new Set(sets[0]); + if (sets.length === 0) return new Set(); + if (sets.length === 1) return new Set(sets[0]); let minSize = Infinity; let minIndex = -1; - for(let i = 0; i < sets.length; i++) { + for (let i = 0; i < sets.length; i++) { const size = sets[i].size; - if(size < minSize) { + if (size < minSize) { minIndex = i; minSize = size; } } const current = new Set(sets[minIndex]); - for(let i = 0; i < sets.length; i++) { - if(i === minIndex) continue; + for (let i = 0; i < sets.length; i++) { + if (i === minIndex) continue; const set = sets[i]; - for(const item of current) { - if(!set.has(item)) { + for (const item of current) { + if (!set.has(item)) { current.delete(item); } } @@ -26,9 +26,9 @@ exports.intersect = sets => { }; exports.isSubset = (bigSet, smallSet) => { - if(bigSet.size < smallSet.size) return false; - for(const item of smallSet) { - if(!bigSet.has(item)) return false; + if (bigSet.size < smallSet.size) return false; + for (const item of smallSet) { + if (!bigSet.has(item)) return false; } return true; }; diff --git a/lib/util/SortableSet.js b/lib/util/SortableSet.js index a1f2896fb..8cdaf4dad 100644 --- a/lib/util/SortableSet.js +++ b/lib/util/SortableSet.js @@ -1,7 +1,6 @@ "use strict"; class SortableSet extends Set { - constructor(initialIterable, defaultSort) { super(initialIterable); this._sortFn = defaultSort; @@ -39,14 +38,14 @@ class SortableSet extends Set { * @returns {void} */ sortWith(sortFn) { - if(this.size === 0 || sortFn === this._lastActiveSortFn) { + if (this.size === 0 || sortFn === this._lastActiveSortFn) { // already sorted - nothing to do return; } const sortedArray = Array.from(this).sort(sortFn); super.clear(); - for(let i = 0; i < sortedArray.length; i += 1) { + for (let i = 0; i < sortedArray.length; i += 1) { super.add(sortedArray[i]); } this._lastActiveSortFn = sortFn; @@ -65,11 +64,11 @@ class SortableSet extends Set { * @returns {any} - returns result of fn(this), cached until set changes */ getFromCache(fn) { - if(this._cache === undefined) { + if (this._cache === undefined) { this._cache = new Map(); } else { const data = this._cache.get(fn); - if(data !== undefined) { + if (data !== undefined) { return data; } } @@ -83,11 +82,11 @@ class SortableSet extends Set { * @returns {any} - returns result of fn(this), cached until set changes */ getFromUnorderedCache(fn) { - if(this._cacheOrderIndependent === undefined) { + if (this._cacheOrderIndependent === undefined) { this._cacheOrderIndependent = new Map(); } else { const data = this._cacheOrderIndependent.get(fn); - if(data !== undefined) { + if (data !== undefined) { return data; } } @@ -97,12 +96,11 @@ class SortableSet extends Set { } _invalidateCache() { - if(this._cache !== undefined) - this._cache.clear(); + if (this._cache !== undefined) this._cache.clear(); } _invalidateOrderedCache() { - if(this._cacheOrderIndependent !== undefined) + if (this._cacheOrderIndependent !== undefined) this._cacheOrderIndependent.clear(); } } diff --git a/lib/util/StackedSetMap.js b/lib/util/StackedSetMap.js index cc36ca663..896b6c4c9 100644 --- a/lib/util/StackedSetMap.js +++ b/lib/util/StackedSetMap.js @@ -25,20 +25,17 @@ class StackedSetMap { } delete(item) { - if(this.stack.length > 1) - this.map.set(item, TOMBSTONE); - else - this.map.delete(item); + if (this.stack.length > 1) this.map.set(item, TOMBSTONE); + else this.map.delete(item); } has(item) { const topValue = this.map.get(item); - if(topValue !== undefined) - return topValue !== TOMBSTONE; - if(this.stack.length > 1) { - for(var i = this.stack.length - 2; i >= 0; i--) { + if (topValue !== undefined) return topValue !== TOMBSTONE; + if (this.stack.length > 1) { + for (var i = this.stack.length - 2; i >= 0; i--) { const value = this.stack[i].get(item); - if(value !== undefined) { + if (value !== undefined) { this.map.set(item, value); return value !== TOMBSTONE; } @@ -50,14 +47,18 @@ class StackedSetMap { get(item) { const topValue = this.map.get(item); - if(topValue !== undefined) - return topValue === TOMBSTONE || topValue === UNDEFINED_MARKER ? undefined : topValue; - if(this.stack.length > 1) { - for(var i = this.stack.length - 2; i >= 0; i--) { + if (topValue !== undefined) + return topValue === TOMBSTONE || topValue === UNDEFINED_MARKER + ? undefined + : topValue; + if (this.stack.length > 1) { + for (var i = this.stack.length - 2; i >= 0; i--) { const value = this.stack[i].get(item); - if(value !== undefined) { + if (value !== undefined) { this.map.set(item, value); - return value === TOMBSTONE || value === UNDEFINED_MARKER ? undefined : value; + return value === TOMBSTONE || value === UNDEFINED_MARKER + ? undefined + : value; } } this.map.set(item, TOMBSTONE); @@ -66,14 +67,12 @@ class StackedSetMap { } _compress() { - if(this.stack.length === 1) return; + if (this.stack.length === 1) return; this.map = new Map(); - for(const data of this.stack) { - for(const pair of data) { - if(pair[1] === TOMBSTONE) - this.map.delete(pair[0]); - else - this.map.set(pair[0], pair[1]); + for (const data of this.stack) { + for (const pair of data) { + if (pair[1] === TOMBSTONE) this.map.delete(pair[0]); + else this.map.set(pair[0], pair[1]); } } this.stack = [this.map]; @@ -90,7 +89,10 @@ class StackedSetMap { asPairArray() { this._compress(); - return Array.from(this.map.entries(), pair => pair[1] === UNDEFINED_MARKER ? [pair[0], undefined] : pair); + return Array.from( + this.map.entries(), + pair => (pair[1] === UNDEFINED_MARKER ? [pair[0], undefined] : pair) + ); } asMap() { diff --git a/lib/util/cachedMerge.js b/lib/util/cachedMerge.js index 182a2aaab..12a0ca905 100644 --- a/lib/util/cachedMerge.js +++ b/lib/util/cachedMerge.js @@ -7,18 +7,18 @@ const mergeCache = new WeakMap(); const cachedMerge = (first, ...args) => { - if(args.length === 0) return first; - if(args.length > 1) { + if (args.length === 0) return first; + if (args.length > 1) { return cachedMerge(first, cachedMerge(...args)); } const second = args[0]; let innerCache = mergeCache.get(first); - if(innerCache === undefined) { + if (innerCache === undefined) { innerCache = new WeakMap(); mergeCache.set(first, innerCache); } const cachedMerge = innerCache.get(second); - if(cachedMerge !== undefined) return cachedMerge; + if (cachedMerge !== undefined) return cachedMerge; const newMerge = Object.assign({}, first, second); innerCache.set(second, newMerge); return newMerge; diff --git a/lib/util/createHash.js b/lib/util/createHash.js index 188edfa4c..2d21d0aa5 100644 --- a/lib/util/createHash.js +++ b/lib/util/createHash.js @@ -13,15 +13,19 @@ class BulkUpdateDecorator { } update(data, inputEncoding) { - if(inputEncoding !== undefined || typeof data !== "string" || data.length > BULK_SIZE) { - if(this.buffer.length > 0) { + if ( + inputEncoding !== undefined || + typeof data !== "string" || + data.length > BULK_SIZE + ) { + if (this.buffer.length > 0) { this.hash.update(this.buffer); this.buffer = ""; } this.hash.update(data, inputEncoding); } else { this.buffer += data; - if(this.buffer.length > BULK_SIZE) { + if (this.buffer.length > BULK_SIZE) { this.hash.update(this.buffer); this.buffer = ""; } @@ -30,11 +34,13 @@ class BulkUpdateDecorator { } digest(encoding) { - if(this.buffer.length > 0) { + if (this.buffer.length > 0) { this.hash.update(this.buffer); } var digestResult = this.hash.digest(encoding); - return typeof digestResult === "string" ? digestResult : digestResult.toString(); + return typeof digestResult === "string" + ? digestResult + : digestResult.toString(); } } @@ -45,21 +51,23 @@ class DebugHash { } update(data, inputEncoding) { - if(typeof data !== "string") data = data.toString("utf-8"); + if (typeof data !== "string") data = data.toString("utf-8"); this.string += data; return this; } digest(encoding) { - return this.string.replace(/[^a-z0-9]+/gi, m => Buffer.from(m).toString("hex")); + return this.string.replace(/[^a-z0-9]+/gi, m => + Buffer.from(m).toString("hex") + ); } } module.exports = algorithm => { - if(typeof algorithm === "function") { + if (typeof algorithm === "function") { return new BulkUpdateDecorator(new algorithm()); } - switch(algorithm) { + switch (algorithm) { // TODO add non-cryptographic algorithm here case "debug": return new DebugHash(); diff --git a/lib/util/identifier.js b/lib/util/identifier.js index 16a44926e..39f271d8b 100644 --- a/lib/util/identifier.js +++ b/lib/util/identifier.js @@ -1,34 +1,39 @@ "use strict"; const path = require("path"); -const looksLikeAbsolutePath = (maybeAbsolutePath) => { +const looksLikeAbsolutePath = maybeAbsolutePath => { return /^(?:[a-z]:\\|\/)/i.test(maybeAbsolutePath); }; -const normalizePathSeparator = (p) => p.replace(/\\/g, "/"); +const normalizePathSeparator = p => p.replace(/\\/g, "/"); const _makePathsRelative = (context, identifier) => { return identifier .split(/([|! ])/) - .map(str => looksLikeAbsolutePath(str) ? - normalizePathSeparator(path.relative(context, str)) : str) + .map( + str => + looksLikeAbsolutePath(str) + ? normalizePathSeparator(path.relative(context, str)) + : str + ) .join(""); }; exports.makePathsRelative = (context, identifier, cache) => { - if(!cache) return _makePathsRelative(context, identifier); + if (!cache) return _makePathsRelative(context, identifier); - const relativePaths = cache.relativePaths || (cache.relativePaths = new Map()); + const relativePaths = + cache.relativePaths || (cache.relativePaths = new Map()); let cachedResult; let contextCache = relativePaths.get(context); - if(typeof contextCache === "undefined") { - relativePaths.set(context, contextCache = new Map()); + if (typeof contextCache === "undefined") { + relativePaths.set(context, (contextCache = new Map())); } else { cachedResult = contextCache.get(identifier); } - if(typeof cachedResult !== "undefined") { + if (typeof cachedResult !== "undefined") { return cachedResult; } else { const relativePath = _makePathsRelative(context, identifier); diff --git a/lib/validateSchema.js b/lib/validateSchema.js index 1806eed3b..b748c2c8f 100644 --- a/lib/validateSchema.js +++ b/lib/validateSchema.js @@ -14,12 +14,12 @@ require("ajv-keywords")(ajv, ["instanceof"]); require("../schemas/ajv.absolutePath")(ajv); const validateSchema = (schema, options) => { - if(Array.isArray(options)) { - const errors = options.map((options) => validateObject(schema, options)); + if (Array.isArray(options)) { + const errors = options.map(options => validateObject(schema, options)); errors.forEach((list, idx) => { const applyPrefix = err => { err.dataPath = `[${idx}]${err.dataPath}`; - if(err.children) { + if (err.children) { err.children.forEach(applyPrefix); } }; @@ -41,12 +41,12 @@ const validateObject = (schema, options) => { const filterErrors = errors => { let newErrors = []; - for(const err of errors) { + for (const err of errors) { const dataPath = err.dataPath; let children = []; - newErrors = newErrors.filter((oldError) => { - if(oldError.dataPath.includes(dataPath)) { - if(oldError.children) { + newErrors = newErrors.filter(oldError => { + if (oldError.dataPath.includes(dataPath)) { + if (oldError.children) { children = children.concat(oldError.children.slice(0)); } oldError.children = undefined; @@ -55,7 +55,7 @@ const filterErrors = errors => { } return true; }); - if(children.length) { + if (children.length) { err.children = children; } newErrors.push(err); diff --git a/lib/wasm/WasmModuleTemplatePlugin.js b/lib/wasm/WasmModuleTemplatePlugin.js index 96ecfa2b6..752033e72 100644 --- a/lib/wasm/WasmModuleTemplatePlugin.js +++ b/lib/wasm/WasmModuleTemplatePlugin.js @@ -9,72 +9,93 @@ const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDe class WasmModuleTemplatePlugin { apply(moduleTemplate) { - moduleTemplate.hooks.content.tap("WasmModuleTemplatePlugin", (moduleSource, module, { - chunk - }) => { - if(module.type && module.type.startsWith("webassembly")) { - if(chunk.canBeInitial()) - throw new Error("Sync WebAssembly compilation is not yet implemented"); - const generateExports = () => { - if(Array.isArray(module.buildMeta.providedExports) && Array.isArray(module.usedExports)) { - // generate mangled exports - return module.buildMeta.providedExports.map(exp => { - const usedName = module.isUsed(exp); - if(usedName) { - return `${module.exportsArgument}[${JSON.stringify(usedName)}] = instance.exports[${JSON.stringify(exp)}];`; - } else { - return `// unused ${JSON.stringify(exp)} export`; - } - }).join("\n"); - } else { - // generate simple export - return `${module.moduleArgument}.exports = instance.exports;`; - } - }; - const generateImports = () => { - const depsByRequest = new Map(); - for(const dep of module.dependencies) { - if(dep instanceof WebAssemblyImportDependency) { - const request = dep.request; - let array = depsByRequest.get(request); - if(!array) { - depsByRequest.set(request, array = []); - } - const exportName = dep.name; - const usedName = dep.module && dep.module.isUsed(exportName); - array.push({ - exportName, - usedName, - module: dep.module - }); + moduleTemplate.hooks.content.tap( + "WasmModuleTemplatePlugin", + (moduleSource, module, { chunk }) => { + if (module.type && module.type.startsWith("webassembly")) { + if (chunk.canBeInitial()) + throw new Error( + "Sync WebAssembly compilation is not yet implemented" + ); + const generateExports = () => { + if ( + Array.isArray(module.buildMeta.providedExports) && + Array.isArray(module.usedExports) + ) { + // generate mangled exports + return module.buildMeta.providedExports + .map(exp => { + const usedName = module.isUsed(exp); + if (usedName) { + return `${module.exportsArgument}[${JSON.stringify( + usedName + )}] = instance.exports[${JSON.stringify(exp)}];`; + } else { + return `// unused ${JSON.stringify(exp)} export`; + } + }) + .join("\n"); + } else { + // generate simple export + return `${module.moduleArgument}.exports = instance.exports;`; } - } - const importsCode = []; - for(const pair of depsByRequest) { - const properties = []; - for(const data of pair[1]) { - properties.push(`\n\t\t${JSON.stringify(data.exportName)}: __webpack_require__(${JSON.stringify(data.module.id)})[${JSON.stringify(data.usedName)}]`); + }; + const generateImports = () => { + const depsByRequest = new Map(); + for (const dep of module.dependencies) { + if (dep instanceof WebAssemblyImportDependency) { + const request = dep.request; + let array = depsByRequest.get(request); + if (!array) { + depsByRequest.set(request, (array = [])); + } + const exportName = dep.name; + const usedName = dep.module && dep.module.isUsed(exportName); + array.push({ + exportName, + usedName, + module: dep.module + }); + } } - importsCode.push(`\n\t${JSON.stringify(pair[0])}: {${properties.join(",")}\n\t}`); - } - return importsCode.join(","); - }; - const source = new RawSource([ - "\"use strict\";", - "", - "// Instantiate WebAssembly module", - "var instance = new WebAssembly.Instance(__webpack_require__.w[module.i], {" + generateImports(), - "});", - "", - "// export exports from WebAssembly module", - // TODO rewrite this to getters depending on exports to support circular dependencies - generateExports() - ].join("\n")); - return source; - } else { - return moduleSource; + const importsCode = []; + for (const pair of depsByRequest) { + const properties = []; + for (const data of pair[1]) { + properties.push( + `\n\t\t${JSON.stringify( + data.exportName + )}: __webpack_require__(${JSON.stringify( + data.module.id + )})[${JSON.stringify(data.usedName)}]` + ); + } + importsCode.push( + `\n\t${JSON.stringify(pair[0])}: {${properties.join(",")}\n\t}` + ); + } + return importsCode.join(","); + }; + const source = new RawSource( + [ + '"use strict";', + "", + "// Instantiate WebAssembly module", + "var instance = new WebAssembly.Instance(__webpack_require__.w[module.i], {" + + generateImports(), + "});", + "", + "// export exports from WebAssembly module", + // TODO rewrite this to getters depending on exports to support circular dependencies + generateExports() + ].join("\n") + ); + return source; + } else { + return moduleSource; + } } - }); + ); moduleTemplate.hooks.hash.tap("WasmModuleTemplatePlugin", hash => { hash.update("WasmModuleTemplatePlugin"); diff --git a/lib/web/FetchCompileWasmMainTemplatePlugin.js b/lib/web/FetchCompileWasmMainTemplatePlugin.js index 3ab116cb0..447f695db 100644 --- a/lib/web/FetchCompileWasmMainTemplatePlugin.js +++ b/lib/web/FetchCompileWasmMainTemplatePlugin.js @@ -7,81 +7,108 @@ const Template = require("../Template"); class FetchCompileWasmMainTemplatePlugin { - apply(mainTemplate) { - mainTemplate.hooks.localVars.tap("FetchCompileWasmMainTemplatePlugin", (source, chunk) => { - if(!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly"))) - return source; - return Template.asString([ - source, - "", - "// object to store loaded and loading wasm modules", - "var installedWasmModules = {};", - ]); - }); - mainTemplate.hooks.requireEnsure.tap("FetchCompileWasmMainTemplatePlugin", (source, chunk, hash) => { - const webassemblyModuleFilename = mainTemplate.outputOptions.webassemblyModuleFilename; - const chunkModuleMaps = chunk.getChunkModuleMaps(m => m.type.startsWith("webassembly")); - if(Object.keys(chunkModuleMaps.id).length === 0) return source; - const wasmModuleSrcPath = mainTemplate.getAssetPath(JSON.stringify(webassemblyModuleFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - module: { - id: "\" + wasmModuleId + \"", - hash: `" + ${JSON.stringify(chunkModuleMaps.hash)}[wasmModuleId] + "`, - hashWithLength(length) { - const shortChunkHashMap = Object.create(null); - for(const wasmModuleId of Object.keys(chunkModuleMaps.hash)) { - if(typeof chunkModuleMaps.hash[wasmModuleId] === "string") - shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[wasmModuleId].substr(0, length); - } - return `" + ${JSON.stringify(shortChunkHashMap)}[wasmModuleId] + "`; - } - } - }); - return Template.asString([ - source, - "", - "// Fetch + compile chunk loading for webassembly", - "", - `var wasmModules = ${JSON.stringify(chunkModuleMaps.id)}[chunkId] || [];`, - "", - "wasmModules.forEach(function(wasmModuleId) {", - Template.indent([ - "var installedWasmModuleData = installedWasmModules[wasmModuleId];", + mainTemplate.hooks.localVars.tap( + "FetchCompileWasmMainTemplatePlugin", + (source, chunk) => { + if (!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly"))) + return source; + return Template.asString([ + source, "", - "// a Promise means \"currently loading\" or \"already loaded\".", - "promises.push(installedWasmModuleData ||", + "// object to store loaded and loading wasm modules", + "var installedWasmModules = {};" + ]); + } + ); + mainTemplate.hooks.requireEnsure.tap( + "FetchCompileWasmMainTemplatePlugin", + (source, chunk, hash) => { + const webassemblyModuleFilename = + mainTemplate.outputOptions.webassemblyModuleFilename; + const chunkModuleMaps = chunk.getChunkModuleMaps(m => + m.type.startsWith("webassembly") + ); + if (Object.keys(chunkModuleMaps.id).length === 0) return source; + const wasmModuleSrcPath = mainTemplate.getAssetPath( + JSON.stringify(webassemblyModuleFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + module: { + id: '" + wasmModuleId + "', + hash: `" + ${JSON.stringify( + chunkModuleMaps.hash + )}[wasmModuleId] + "`, + hashWithLength(length) { + const shortChunkHashMap = Object.create(null); + for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) { + if (typeof chunkModuleMaps.hash[wasmModuleId] === "string") + shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[ + wasmModuleId + ].substr(0, length); + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[wasmModuleId] + "`; + } + } + } + ); + return Template.asString([ + source, + "", + "// Fetch + compile chunk loading for webassembly", + "", + `var wasmModules = ${JSON.stringify( + chunkModuleMaps.id + )}[chunkId] || [];`, + "", + "wasmModules.forEach(function(wasmModuleId) {", Template.indent([ - `(installedWasmModules[wasmModuleId] = fetch(${mainTemplate.requireFn}.p + ${wasmModuleSrcPath}).then(function(response) {`, + "var installedWasmModuleData = installedWasmModules[wasmModuleId];", + "", + '// a Promise means "currently loading" or "already loaded".', + "promises.push(installedWasmModuleData ||", Template.indent([ - "if(WebAssembly.compileStreaming) {", + `(installedWasmModules[wasmModuleId] = fetch(${ + mainTemplate.requireFn + }.p + ${wasmModuleSrcPath}).then(function(response) {`, Template.indent([ - "return WebAssembly.compileStreaming(response);" + "if(WebAssembly.compileStreaming) {", + Template.indent([ + "return WebAssembly.compileStreaming(response);" + ]), + "} else {", + Template.indent([ + "return response.arrayBuffer().then(function(bytes) { return WebAssembly.compile(bytes); });" + ]), + "}" ]), - "} else {", - Template.indent([ - "return response.arrayBuffer().then(function(bytes) { return WebAssembly.compile(bytes); });", - ]), - "}" + `}).then(function(module) { ${ + mainTemplate.requireFn + }.w[wasmModuleId] = module; }))` ]), - `}).then(function(module) { ${mainTemplate.requireFn}.w[wasmModuleId] = module; }))` + ");" ]), - ");", - ]), - "});", - ]); - }); - mainTemplate.hooks.requireExtensions.tap("FetchCompileWasmMainTemplatePlugin", (source, chunk) => { - if(!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly"))) - return source; - return Template.asString([ - source, - "", - "// object with all compiled WebAssmbly.Modules", - `${mainTemplate.requireFn}.w = {};` - ]); - }); + "});" + ]); + } + ); + mainTemplate.hooks.requireExtensions.tap( + "FetchCompileWasmMainTemplatePlugin", + (source, chunk) => { + if (!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly"))) + return source; + return Template.asString([ + source, + "", + "// object with all compiled WebAssmbly.Modules", + `${mainTemplate.requireFn}.w = {};` + ]); + } + ); mainTemplate.hooks.hash.tap("FetchCompileWasmMainTemplatePlugin", hash => { hash.update("FetchCompileWasmMainTemplatePlugin"); hash.update("1"); diff --git a/lib/web/FetchCompileWasmTemplatePlugin.js b/lib/web/FetchCompileWasmTemplatePlugin.js index 9b6cf0419..07263faa0 100644 --- a/lib/web/FetchCompileWasmTemplatePlugin.js +++ b/lib/web/FetchCompileWasmTemplatePlugin.js @@ -9,10 +9,17 @@ const WasmModuleTemplatePlugin = require("../wasm/WasmModuleTemplatePlugin"); class FetchCompileWasmTemplatePlugin { apply(compiler) { - compiler.hooks.thisCompilation.tap("FetchCompileWasmTemplatePlugin", (compilation) => { - new FetchCompileWasmMainTemplatePlugin().apply(compilation.mainTemplate); - new WasmModuleTemplatePlugin().apply(compilation.moduleTemplates.javascript); - }); + compiler.hooks.thisCompilation.tap( + "FetchCompileWasmTemplatePlugin", + compilation => { + new FetchCompileWasmMainTemplatePlugin().apply( + compilation.mainTemplate + ); + new WasmModuleTemplatePlugin().apply( + compilation.moduleTemplates.javascript + ); + } + ); } } diff --git a/lib/web/JsonpChunkTemplatePlugin.js b/lib/web/JsonpChunkTemplatePlugin.js index bdfc48fa2..161b6cf24 100644 --- a/lib/web/JsonpChunkTemplatePlugin.js +++ b/lib/web/JsonpChunkTemplatePlugin.js @@ -8,21 +8,34 @@ const ConcatSource = require("webpack-sources").ConcatSource; class JsonpChunkTemplatePlugin { apply(chunkTemplate) { - chunkTemplate.hooks.render.tap("JsonpChunkTemplatePlugin", (modules, chunk) => { - const jsonpFunction = chunkTemplate.outputOptions.jsonpFunction; - const globalObject = chunkTemplate.outputOptions.globalObject; - const source = new ConcatSource(); - source.add(`(${globalObject}[${JSON.stringify(jsonpFunction)}] = ${globalObject}[${JSON.stringify(jsonpFunction)}] || []).push([${JSON.stringify(chunk.ids)},`); - source.add(modules); - const entries = [chunk.entryModule] - .filter(Boolean) - .map(m => [m.id].concat(Array.from(chunk.groupsIterable)[0].chunks.filter(c => c !== chunk).map(c => c.id))); - if(entries.length > 0) { - source.add(`,${JSON.stringify(entries)}`); + chunkTemplate.hooks.render.tap( + "JsonpChunkTemplatePlugin", + (modules, chunk) => { + const jsonpFunction = chunkTemplate.outputOptions.jsonpFunction; + const globalObject = chunkTemplate.outputOptions.globalObject; + const source = new ConcatSource(); + source.add( + `(${globalObject}[${JSON.stringify(jsonpFunction)}] = ${ + globalObject + }[${JSON.stringify(jsonpFunction)}] || []).push([${JSON.stringify( + chunk.ids + )},` + ); + source.add(modules); + const entries = [chunk.entryModule].filter(Boolean).map(m => + [m.id].concat( + Array.from(chunk.groupsIterable)[0] + .chunks.filter(c => c !== chunk) + .map(c => c.id) + ) + ); + if (entries.length > 0) { + source.add(`,${JSON.stringify(entries)}`); + } + source.add("])"); + return source; } - source.add("])"); - return source; - }); + ); chunkTemplate.hooks.hash.tap("JsonpChunkTemplatePlugin", hash => { hash.update("JsonpChunkTemplatePlugin"); hash.update("4"); diff --git a/lib/web/JsonpExportMainTemplatePlugin.js b/lib/web/JsonpExportMainTemplatePlugin.js index 4b08e514d..46e400587 100644 --- a/lib/web/JsonpExportMainTemplatePlugin.js +++ b/lib/web/JsonpExportMainTemplatePlugin.js @@ -12,10 +12,7 @@ class JsonpExportMainTemplatePlugin { } apply(compilation) { - const { - mainTemplate, - chunkTemplate - } = compilation; + const { mainTemplate, chunkTemplate } = compilation; const onRenderWithEntry = (source, chunk, hash) => { const name = mainTemplate.getAssetPath(this.name || "", { @@ -25,14 +22,20 @@ class JsonpExportMainTemplatePlugin { return new ConcatSource(`${name}(`, source, ");"); }; - for(const template of [mainTemplate, chunkTemplate]) { - template.hooks.renderWithEntry.tap("JsonpExportMainTemplatePlugin", onRenderWithEntry); + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "JsonpExportMainTemplatePlugin", + onRenderWithEntry + ); } - mainTemplate.hooks.globalHashPaths.tap("JsonpExportMainTemplatePlugin", paths => { - if(this.name) paths.push(this.name); - return paths; - }); + mainTemplate.hooks.globalHashPaths.tap( + "JsonpExportMainTemplatePlugin", + paths => { + if (this.name) paths.push(this.name); + return paths; + } + ); mainTemplate.hooks.hash.tap("JsonpExportMainTemplatePlugin", hash => { hash.update("jsonp export"); diff --git a/lib/web/JsonpHotUpdateChunkTemplatePlugin.js b/lib/web/JsonpHotUpdateChunkTemplatePlugin.js index 6269d834f..a31d5dc6e 100644 --- a/lib/web/JsonpHotUpdateChunkTemplatePlugin.js +++ b/lib/web/JsonpHotUpdateChunkTemplatePlugin.js @@ -8,19 +8,31 @@ const ConcatSource = require("webpack-sources").ConcatSource; class JsonpHotUpdateChunkTemplatePlugin { apply(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.hooks.render.tap("JsonpHotUpdateChunkTemplatePlugin", (modulesSource, modules, removedModules, hash, id) => { - const source = new ConcatSource(); - source.add(`${hotUpdateChunkTemplate.outputOptions.hotUpdateFunction}(${JSON.stringify(id)},`); - source.add(modulesSource); - source.add(")"); - return source; - }); - hotUpdateChunkTemplate.hooks.hash.tap("JsonpHotUpdateChunkTemplatePlugin", hash => { - hash.update("JsonpHotUpdateChunkTemplatePlugin"); - hash.update("3"); - hash.update(`${hotUpdateChunkTemplate.outputOptions.hotUpdateFunction}`); - hash.update(`${hotUpdateChunkTemplate.outputOptions.library}`); - }); + hotUpdateChunkTemplate.hooks.render.tap( + "JsonpHotUpdateChunkTemplatePlugin", + (modulesSource, modules, removedModules, hash, id) => { + const source = new ConcatSource(); + source.add( + `${ + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + }(${JSON.stringify(id)},` + ); + source.add(modulesSource); + source.add(")"); + return source; + } + ); + hotUpdateChunkTemplate.hooks.hash.tap( + "JsonpHotUpdateChunkTemplatePlugin", + hash => { + hash.update("JsonpHotUpdateChunkTemplatePlugin"); + hash.update("3"); + hash.update( + `${hotUpdateChunkTemplate.outputOptions.hotUpdateFunction}` + ); + hash.update(`${hotUpdateChunkTemplate.outputOptions.library}`); + } + ); } } diff --git a/lib/web/JsonpMainTemplate.runtime.js b/lib/web/JsonpMainTemplate.runtime.js index 58131de7d..a4e32efe4 100644 --- a/lib/web/JsonpMainTemplate.runtime.js +++ b/lib/web/JsonpMainTemplate.runtime.js @@ -4,12 +4,14 @@ */ /*globals hotAddUpdateChunk parentHotUpdateCallback document XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ $crossOriginLoading$ */ module.exports = function() { - function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars + function webpackHotUpdateCallback(chunkId, moreModules) { + // eslint-disable-line no-unused-vars hotAddUpdateChunk(chunkId, moreModules); - if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); + if (parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); } //$semicolon - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + // eslint-disable-line no-unused-vars var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.charset = "utf-8"; @@ -18,10 +20,11 @@ module.exports = function() { head.appendChild(script); } - function hotDownloadManifest(requestTimeout) { // eslint-disable-line no-unused-vars + function hotDownloadManifest(requestTimeout) { + // eslint-disable-line no-unused-vars requestTimeout = requestTimeout || 10000; return new Promise(function(resolve, reject) { - if(typeof XMLHttpRequest === "undefined") + if (typeof XMLHttpRequest === "undefined") return reject(new Error("No browser support")); try { var request = new XMLHttpRequest(); @@ -29,25 +32,27 @@ module.exports = function() { request.open("GET", requestPath, true); request.timeout = requestTimeout; request.send(null); - } catch(err) { + } catch (err) { return reject(err); } request.onreadystatechange = function() { - if(request.readyState !== 4) return; - if(request.status === 0) { + if (request.readyState !== 4) return; + if (request.status === 0) { // timeout - reject(new Error("Manifest request to " + requestPath + " timed out.")); - } else if(request.status === 404) { + reject( + new Error("Manifest request to " + requestPath + " timed out.") + ); + } else if (request.status === 404) { // no update available resolve(); - } else if(request.status !== 200 && request.status !== 304) { + } else if (request.status !== 200 && request.status !== 304) { // other failure reject(new Error("Manifest request to " + requestPath + " failed.")); } else { // success try { var update = JSON.parse(request.responseText); - } catch(e) { + } catch (e) { reject(e); return; } diff --git a/lib/web/JsonpMainTemplatePlugin.js b/lib/web/JsonpMainTemplatePlugin.js index e926ef0ea..28e02dfbf 100644 --- a/lib/web/JsonpMainTemplatePlugin.js +++ b/lib/web/JsonpMainTemplatePlugin.js @@ -8,302 +8,388 @@ const Template = require("../Template"); const SyncWaterfallHook = require("tapable").SyncWaterfallHook; class JsonpMainTemplatePlugin { - apply(mainTemplate) { const needChunkOnDemandLoadingCode = chunk => { - for(const chunkGroup of chunk.groupsIterable) { - if(chunkGroup.getNumberOfChildren() > 0) return true; + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.getNumberOfChildren() > 0) return true; } return false; }; const needChunkLoadingCode = chunk => { - for(const chunkGroup of chunk.groupsIterable) { - if(chunkGroup.chunks.length > 1) return true; - if(chunkGroup.getNumberOfChildren() > 0) return true; + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.chunks.length > 1) return true; + if (chunkGroup.getNumberOfChildren() > 0) return true; } return false; }; const needEntryDeferringCode = chunk => { - for(const chunkGroup of chunk.groupsIterable) { - if(chunkGroup.chunks.length > 1) return true; + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.chunks.length > 1) return true; } return false; }; // TODO refactor this - if(!mainTemplate.hooks.jsonpScript) { - mainTemplate.hooks.jsonpScript = new SyncWaterfallHook(["source", "chunk", "hash"]); + if (!mainTemplate.hooks.jsonpScript) { + mainTemplate.hooks.jsonpScript = new SyncWaterfallHook([ + "source", + "chunk", + "hash" + ]); } - mainTemplate.hooks.localVars.tap("JsonpMainTemplatePlugin", (source, chunk) => { - if(needChunkLoadingCode(chunk)) { + mainTemplate.hooks.localVars.tap( + "JsonpMainTemplatePlugin", + (source, chunk) => { + if (needChunkLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// object to store loaded and loading chunks", + "var installedChunks = {", + Template.indent( + chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n") + ), + "};", + "", + needEntryDeferringCode(chunk) ? "var deferredModules = [];" : "" + ]); + } + return source; + } + ); + mainTemplate.hooks.jsonpScript.tap( + "JsonpMainTemplatePlugin", + (_, chunk, hash) => { + const chunkFilename = mainTemplate.outputOptions.chunkFilename; + const chunkMaps = chunk.getChunkMaps(); + const crossOriginLoading = + mainTemplate.outputOptions.crossOriginLoading; + const chunkLoadTimeout = mainTemplate.outputOptions.chunkLoadTimeout; + const jsonpScriptType = mainTemplate.outputOptions.jsonpScriptType; + const scriptSrcPath = mainTemplate.getAssetPath( + JSON.stringify(chunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength(length) { + const shortChunkHashMap = Object.create(null); + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") + shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr( + 0, + length + ); + } + return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + } + } + ); return Template.asString([ - source, - "", - "// object to store loaded and loading chunks", - "var installedChunks = {", + "var script = document.createElement('script');", + jsonpScriptType + ? `script.type = ${JSON.stringify(jsonpScriptType)};` + : "", + "script.charset = 'utf-8';", + `script.timeout = ${chunkLoadTimeout};`, + crossOriginLoading + ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` + : "", + `if (${mainTemplate.requireFn}.nc) {`, Template.indent( - chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n") + `script.setAttribute("nonce", ${mainTemplate.requireFn}.nc);` ), - "};", - "", - needEntryDeferringCode(chunk) ? "var deferredModules = [];" : "" + "}", + `script.src = ${mainTemplate.requireFn}.p + ${scriptSrcPath};`, + "var timeout = setTimeout(function(){", + Template.indent([ + "onScriptComplete({ type: 'timeout', target: script });" + ]), + `}, ${chunkLoadTimeout});`, + "script.onerror = script.onload = onScriptComplete;", + "function onScriptComplete(event) {", + Template.indent([ + "// avoid mem leaks in IE.", + "script.onerror = script.onload = null;", + "clearTimeout(timeout);", + "var chunk = installedChunks[chunkId];", + "if(chunk !== 0) {", + Template.indent([ + "if(chunk) {", + Template.indent([ + "var errorType = event && (event.type === 'load' ? 'missing' : event.type);", + "var realSrc = event && event.target && event.target.src;", + "var error = new Error('Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')');", + "error.type = errorType;", + "error.request = realSrc;", + "chunk[1](error);" + ]), + "}", + "installedChunks[chunkId] = undefined;" + ]), + "}" + ]), + "};" ]); } - return source; - }); - mainTemplate.hooks.jsonpScript.tap("JsonpMainTemplatePlugin", (_, chunk, hash) => { - const chunkFilename = mainTemplate.outputOptions.chunkFilename; - const chunkMaps = chunk.getChunkMaps(); - const crossOriginLoading = mainTemplate.outputOptions.crossOriginLoading; - const chunkLoadTimeout = mainTemplate.outputOptions.chunkLoadTimeout; - const jsonpScriptType = mainTemplate.outputOptions.jsonpScriptType; - const scriptSrcPath = mainTemplate.getAssetPath(JSON.stringify(chunkFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength(length) { - const shortChunkHashMap = Object.create(null); - for(const chunkId of Object.keys(chunkMaps.hash)) { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); - } - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }); - return Template.asString([ - "var script = document.createElement('script');", - jsonpScriptType ? `script.type = ${JSON.stringify(jsonpScriptType)};` : "", - "script.charset = 'utf-8';", - `script.timeout = ${chunkLoadTimeout};`, - crossOriginLoading ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` : "", - `if (${mainTemplate.requireFn}.nc) {`, - Template.indent(`script.setAttribute("nonce", ${mainTemplate.requireFn}.nc);`), - "}", - `script.src = ${mainTemplate.requireFn}.p + ${scriptSrcPath};`, - "var timeout = setTimeout(function(){", - Template.indent([ - "onScriptComplete({ type: 'timeout', target: script });", - ]), - `}, ${chunkLoadTimeout});`, - "script.onerror = script.onload = onScriptComplete;", - "function onScriptComplete(event) {", - Template.indent([ - "// avoid mem leaks in IE.", - "script.onerror = script.onload = null;", - "clearTimeout(timeout);", - "var chunk = installedChunks[chunkId];", - "if(chunk !== 0) {", - Template.indent([ - "if(chunk) {", - Template.indent([ - "var errorType = event && (event.type === 'load' ? 'missing' : event.type);", - "var realSrc = event && event.target && event.target.src;", - "var error = new Error('Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')');", - "error.type = errorType;", - "error.request = realSrc;", - "chunk[1](error);" - ]), - "}", - "installedChunks[chunkId] = undefined;" - ]), - "}" - ]), - "};", - ]); - }); - mainTemplate.hooks.requireEnsure.tap("JsonpMainTemplatePlugin", (source, chunk, hash) => { - return Template.asString([ - source, - "", - "// JSONP chunk loading for javascript", - "", - "var installedChunkData = installedChunks[chunkId];", - "if(installedChunkData !== 0) { // 0 means \"already installed\".", - Template.indent([ - "", - "// a Promise means \"currently loading\".", - "if(installedChunkData) {", - Template.indent([ - "promises.push(installedChunkData[2]);" - ]), - "} else {", - Template.indent([ - "// setup Promise in chunk cache", - "var promise = new Promise(function(resolve, reject) {", - Template.indent([ - "installedChunkData = installedChunks[chunkId] = [resolve, reject];" - ]), - "});", - "promises.push(installedChunkData[2] = promise);", - "", - "// start chunk loading", - "var head = document.getElementsByTagName('head')[0];", - mainTemplate.hooks.jsonpScript.call("", chunk, hash), - "head.appendChild(script);" - ]), - "}", - ]), - "}", - ]); - }); - mainTemplate.hooks.requireExtensions.tap("JsonpMainTemplatePlugin", (source, chunk) => { - if(!needChunkOnDemandLoadingCode(chunk)) return source; - - return Template.asString([ - source, - "", - "// on error function for async loading", - `${mainTemplate.requireFn}.oe = function(err) { console.error(err); throw err; };` - ]); - }); - mainTemplate.hooks.bootstrap.tap("JsonpMainTemplatePlugin", (source, chunk, hash) => { - if(needChunkLoadingCode(chunk)) { - const withDefer = needEntryDeferringCode(chunk); + ); + mainTemplate.hooks.requireEnsure.tap( + "JsonpMainTemplatePlugin", + (source, chunk, hash) => { return Template.asString([ source, "", - "// install a JSONP callback for chunk loading", - "function webpackJsonpCallback(data) {", + "// JSONP chunk loading for javascript", + "", + "var installedChunkData = installedChunks[chunkId];", + 'if(installedChunkData !== 0) { // 0 means "already installed".', Template.indent([ - "var chunkIds = data[0];", - "var moreModules = data[1]", - withDefer ? "var executeModules = data[2];" : "", - "// add \"moreModules\" to the modules object,", - "// then flag all \"chunkIds\" as loaded and fire callback", - "var moduleId, chunkId, i = 0, resolves = [];", - "for(;i < chunkIds.length; i++) {", + "", + '// a Promise means "currently loading".', + "if(installedChunkData) {", + Template.indent(["promises.push(installedChunkData[2]);"]), + "} else {", Template.indent([ - "chunkId = chunkIds[i];", - "if(installedChunks[chunkId]) {", - Template.indent("resolves.push(installedChunks[chunkId][0]);"), - "}", - "installedChunks[chunkId] = 0;" - ]), - "}", - "for(moduleId in moreModules) {", - Template.indent([ - "if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {", - Template.indent(mainTemplate.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")), - "}" - ]), - "}", - "if(parentJsonpFunction) parentJsonpFunction(data);", - "while(resolves.length) {", - Template.indent("resolves.shift()();"), - "}", - withDefer ? Template.asString([ - "", - "// add entry modules from loaded chunk to deferred list", - "deferredModules.push.apply(deferredModules, executeModules || []);", - "", - "// run deferred modules when all chunks ready", - "return checkDeferredModules();" - ]) : "" - ]), - "};", - withDefer ? Template.asString([ - "function checkDeferredModules() {", - Template.indent([ - "var result;", - "for(var i = 0; i < deferredModules.length; i++) {", + "// setup Promise in chunk cache", + "var promise = new Promise(function(resolve, reject) {", Template.indent([ - "var deferredModule = deferredModules[i];", - "var fullfilled = true;", - "for(var j = 1; j < deferredModule.length; j++) {", - Template.indent([ - "var depId = deferredModule[j];", - "if(installedChunks[depId] !== 0) fullfilled = false;" - ]), + "installedChunkData = installedChunks[chunkId] = [resolve, reject];" + ]), + "});", + "promises.push(installedChunkData[2] = promise);", + "", + "// start chunk loading", + "var head = document.getElementsByTagName('head')[0];", + mainTemplate.hooks.jsonpScript.call("", chunk, hash), + "head.appendChild(script);" + ]), + "}" + ]), + "}" + ]); + } + ); + mainTemplate.hooks.requireExtensions.tap( + "JsonpMainTemplatePlugin", + (source, chunk) => { + if (!needChunkOnDemandLoadingCode(chunk)) return source; + + return Template.asString([ + source, + "", + "// on error function for async loading", + `${ + mainTemplate.requireFn + }.oe = function(err) { console.error(err); throw err; };` + ]); + } + ); + mainTemplate.hooks.bootstrap.tap( + "JsonpMainTemplatePlugin", + (source, chunk, hash) => { + if (needChunkLoadingCode(chunk)) { + const withDefer = needEntryDeferringCode(chunk); + return Template.asString([ + source, + "", + "// install a JSONP callback for chunk loading", + "function webpackJsonpCallback(data) {", + Template.indent([ + "var chunkIds = data[0];", + "var moreModules = data[1]", + withDefer ? "var executeModules = data[2];" : "", + '// add "moreModules" to the modules object,', + '// then flag all "chunkIds" as loaded and fire callback', + "var moduleId, chunkId, i = 0, resolves = [];", + "for(;i < chunkIds.length; i++) {", + Template.indent([ + "chunkId = chunkIds[i];", + "if(installedChunks[chunkId]) {", + Template.indent("resolves.push(installedChunks[chunkId][0]);"), "}", - "if(fullfilled) {", - Template.indent([ - "deferredModules.splice(i--, 1);", - "result = " + mainTemplate.requireFn + "(" + mainTemplate.requireFn + ".s = deferredModule[0]);", - ]), + "installedChunks[chunkId] = 0;" + ]), + "}", + "for(moduleId in moreModules) {", + Template.indent([ + "if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {", + Template.indent( + mainTemplate.renderAddModule( + hash, + chunk, + "moduleId", + "moreModules[moduleId]" + ) + ), "}" ]), "}", - "return result;", + "if(parentJsonpFunction) parentJsonpFunction(data);", + "while(resolves.length) {", + Template.indent("resolves.shift()();"), + "}", + withDefer + ? Template.asString([ + "", + "// add entry modules from loaded chunk to deferred list", + "deferredModules.push.apply(deferredModules, executeModules || []);", + "", + "// run deferred modules when all chunks ready", + "return checkDeferredModules();" + ]) + : "" ]), - "}" - ]) : "" - ]); - } - return source; - }); - mainTemplate.hooks.beforeStartup.tap("JsonpMainTemplatePlugin", (source, chunk, hash) => { - if(needChunkLoadingCode(chunk)) { - var jsonpFunction = mainTemplate.outputOptions.jsonpFunction; - var globalObject = mainTemplate.outputOptions.globalObject; - return Template.asString([ - `var jsonpArray = ${globalObject}[${JSON.stringify(jsonpFunction)}] = ${globalObject}[${JSON.stringify(jsonpFunction)}] || [];`, - "var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);", - "jsonpArray.push = webpackJsonpCallback;", - "jsonpArray = jsonpArray.slice();", - "for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);", - "var parentJsonpFunction = oldJsonpFunction;", - "", - source - ]); - } - return source; - }); - mainTemplate.hooks.startup.tap("JsonpMainTemplatePlugin", (source, chunk, hash) => { - if(needEntryDeferringCode(chunk)) { - if(chunk.hasEntryModule()) { - const entries = [chunk.entryModule] - .filter(Boolean) - .map(m => [m.id].concat(Array.from(chunk.groupsIterable)[0].chunks.filter(c => c !== chunk).map(c => c.id))); - return Template.asString([ - "// add entry module to deferred list", - `deferredModules.push(${entries.map(e => JSON.stringify(e)).join(", ")});`, - "// run deferred modules when ready", - "return checkDeferredModules();" - ]); - } else { - return Template.asString([ - "// run deferred modules from other chunks", - "checkDeferredModules();" + "};", + withDefer + ? Template.asString([ + "function checkDeferredModules() {", + Template.indent([ + "var result;", + "for(var i = 0; i < deferredModules.length; i++) {", + Template.indent([ + "var deferredModule = deferredModules[i];", + "var fullfilled = true;", + "for(var j = 1; j < deferredModule.length; j++) {", + Template.indent([ + "var depId = deferredModule[j];", + "if(installedChunks[depId] !== 0) fullfilled = false;" + ]), + "}", + "if(fullfilled) {", + Template.indent([ + "deferredModules.splice(i--, 1);", + "result = " + + mainTemplate.requireFn + + "(" + + mainTemplate.requireFn + + ".s = deferredModule[0]);" + ]), + "}" + ]), + "}", + "return result;" + ]), + "}" + ]) + : "" ]); } + return source; } - return source; - }); - mainTemplate.hooks.hotBootstrap.tap("JsonpMainTemplatePlugin", (source, chunk, hash) => { - const globalObject = mainTemplate.outputOptions.globalObject; - const hotUpdateChunkFilename = mainTemplate.outputOptions.hotUpdateChunkFilename; - const hotUpdateMainFilename = mainTemplate.outputOptions.hotUpdateMainFilename; - const crossOriginLoading = mainTemplate.outputOptions.crossOriginLoading; - const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction; - const currentHotUpdateChunkFilename = mainTemplate.getAssetPath(JSON.stringify(hotUpdateChunkFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"" + ); + mainTemplate.hooks.beforeStartup.tap( + "JsonpMainTemplatePlugin", + (source, chunk, hash) => { + if (needChunkLoadingCode(chunk)) { + var jsonpFunction = mainTemplate.outputOptions.jsonpFunction; + var globalObject = mainTemplate.outputOptions.globalObject; + return Template.asString([ + `var jsonpArray = ${globalObject}[${JSON.stringify( + jsonpFunction + )}] = ${globalObject}[${JSON.stringify(jsonpFunction)}] || [];`, + "var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);", + "jsonpArray.push = webpackJsonpCallback;", + "jsonpArray = jsonpArray.slice();", + "for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);", + "var parentJsonpFunction = oldJsonpFunction;", + "", + source + ]); } - }); - const currentHotUpdateMainFilename = mainTemplate.getAssetPath(JSON.stringify(hotUpdateMainFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` - }); - const runtimeSource = Template.getFunctionContent(require("./JsonpMainTemplate.runtime.js")) - .replace(/\/\/\$semicolon/g, ";") - .replace(/\$require\$/g, mainTemplate.requireFn) - .replace(/\$crossOriginLoading\$/g, crossOriginLoading ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)}` : "") - .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) - .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) - .replace(/\$hash\$/g, JSON.stringify(hash)); - return `${source} + return source; + } + ); + mainTemplate.hooks.startup.tap( + "JsonpMainTemplatePlugin", + (source, chunk, hash) => { + if (needEntryDeferringCode(chunk)) { + if (chunk.hasEntryModule()) { + const entries = [chunk.entryModule].filter(Boolean).map(m => + [m.id].concat( + Array.from(chunk.groupsIterable)[0] + .chunks.filter(c => c !== chunk) + .map(c => c.id) + ) + ); + return Template.asString([ + "// add entry module to deferred list", + `deferredModules.push(${entries + .map(e => JSON.stringify(e)) + .join(", ")});`, + "// run deferred modules when ready", + "return checkDeferredModules();" + ]); + } else { + return Template.asString([ + "// run deferred modules from other chunks", + "checkDeferredModules();" + ]); + } + } + return source; + } + ); + mainTemplate.hooks.hotBootstrap.tap( + "JsonpMainTemplatePlugin", + (source, chunk, hash) => { + const globalObject = mainTemplate.outputOptions.globalObject; + const hotUpdateChunkFilename = + mainTemplate.outputOptions.hotUpdateChunkFilename; + const hotUpdateMainFilename = + mainTemplate.outputOptions.hotUpdateMainFilename; + const crossOriginLoading = + mainTemplate.outputOptions.crossOriginLoading; + const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction; + const currentHotUpdateChunkFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateChunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "' + } + } + ); + const currentHotUpdateMainFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateMainFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` + } + ); + const runtimeSource = Template.getFunctionContent( + require("./JsonpMainTemplate.runtime.js") + ) + .replace(/\/\/\$semicolon/g, ";") + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace( + /\$crossOriginLoading\$/g, + crossOriginLoading + ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)}` + : "" + ) + .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) + .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) + .replace(/\$hash\$/g, JSON.stringify(hash)); + return `${source} function hotDisposeChunk(chunkId) { delete installedChunks[chunkId]; } -var parentHotUpdateCallback = ${globalObject}[${JSON.stringify(hotUpdateFunction)}]; +var parentHotUpdateCallback = ${globalObject}[${JSON.stringify( + hotUpdateFunction + )}]; ${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ${runtimeSource}`; - }); + } + ); mainTemplate.hooks.hash.tap("JsonpMainTemplatePlugin", hash => { hash.update("jsonp"); hash.update("5"); diff --git a/lib/web/JsonpTemplatePlugin.js b/lib/web/JsonpTemplatePlugin.js index 8917014e8..80a6b5b40 100644 --- a/lib/web/JsonpTemplatePlugin.js +++ b/lib/web/JsonpTemplatePlugin.js @@ -10,10 +10,12 @@ const JsonpHotUpdateChunkTemplatePlugin = require("./JsonpHotUpdateChunkTemplate class JsonpTemplatePlugin { apply(compiler) { - compiler.hooks.thisCompilation.tap("JsonpTemplatePlugin", (compilation) => { + compiler.hooks.thisCompilation.tap("JsonpTemplatePlugin", compilation => { new JsonpMainTemplatePlugin().apply(compilation.mainTemplate); new JsonpChunkTemplatePlugin().apply(compilation.chunkTemplate); - new JsonpHotUpdateChunkTemplatePlugin().apply(compilation.hotUpdateChunkTemplate); + new JsonpHotUpdateChunkTemplatePlugin().apply( + compilation.hotUpdateChunkTemplate + ); }); } } diff --git a/lib/webpack.js b/lib/webpack.js index da5d53923..04a3b0d10 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -15,21 +15,24 @@ const webpackOptionsSchema = require("../schemas/WebpackOptions.json"); const RemovedPluginError = require("./RemovedPluginError"); const webpack = (options, callback) => { - const webpackOptionsValidationErrors = validateSchema(webpackOptionsSchema, options); - if(webpackOptionsValidationErrors.length) { + const webpackOptionsValidationErrors = validateSchema( + webpackOptionsSchema, + options + ); + if (webpackOptionsValidationErrors.length) { throw new WebpackOptionsValidationError(webpackOptionsValidationErrors); } let compiler; - if(Array.isArray(options)) { + if (Array.isArray(options)) { compiler = new MultiCompiler(options.map(options => webpack(options))); - } else if(typeof options === "object") { + } else if (typeof options === "object") { options = new WebpackOptionsDefaulter().process(options); compiler = new Compiler(options.context); compiler.options = options; new NodeEnvironmentPlugin().apply(compiler); - if(options.plugins && Array.isArray(options.plugins)) { - for(const plugin of options.plugins) { + if (options.plugins && Array.isArray(options.plugins)) { + for (const plugin of options.plugins) { plugin.apply(compiler); } } @@ -39,10 +42,16 @@ const webpack = (options, callback) => { } else { throw new Error("Invalid argument: options"); } - if(callback) { - if(typeof callback !== "function") throw new Error("Invalid argument: callback"); - if(options.watch === true || (Array.isArray(options) && options.some(o => o.watch))) { - const watchOptions = Array.isArray(options) ? options.map(o => o.watchOptions || {}) : (options.watchOptions || {}); + if (callback) { + if (typeof callback !== "function") + throw new Error("Invalid argument: callback"); + if ( + options.watch === true || + (Array.isArray(options) && options.some(o => o.watch)) + ) { + const watchOptions = Array.isArray(options) + ? options.map(o => o.watchOptions || {}) + : options.watchOptions || {}; return compiler.watch(watchOptions, callback); } compiler.run(callback); @@ -62,7 +71,7 @@ webpack.validateSchema = validateSchema; webpack.WebpackOptionsValidationError = WebpackOptionsValidationError; const exportPlugins = (obj, mappings) => { - for(const name of Object.keys(mappings)) { + for (const name of Object.keys(mappings)) { Object.defineProperty(obj, name, { configurable: false, enumerable: true, @@ -72,66 +81,72 @@ const exportPlugins = (obj, mappings) => { }; exportPlugins(exports, { - "AutomaticPrefetchPlugin": () => require("./AutomaticPrefetchPlugin"), - "BannerPlugin": () => require("./BannerPlugin"), - "CachePlugin": () => require("./CachePlugin"), - "ContextExclusionPlugin": () => require("./ContextExclusionPlugin"), - "ContextReplacementPlugin": () => require("./ContextReplacementPlugin"), - "DefinePlugin": () => require("./DefinePlugin"), - "DllPlugin": () => require("./DllPlugin"), - "DllReferencePlugin": () => require("./DllReferencePlugin"), - "EnvironmentPlugin": () => require("./EnvironmentPlugin"), - "EvalDevToolModulePlugin": () => require("./EvalDevToolModulePlugin"), - "EvalSourceMapDevToolPlugin": () => require("./EvalSourceMapDevToolPlugin"), - "ExtendedAPIPlugin": () => require("./ExtendedAPIPlugin"), - "ExternalsPlugin": () => require("./ExternalsPlugin"), - "HashedModuleIdsPlugin": () => require("./HashedModuleIdsPlugin"), - "HotModuleReplacementPlugin": () => require("./HotModuleReplacementPlugin"), - "IgnorePlugin": () => require("./IgnorePlugin"), - "LibraryTemplatePlugin": () => require("./LibraryTemplatePlugin"), - "LoaderOptionsPlugin": () => require("./LoaderOptionsPlugin"), - "LoaderTargetPlugin": () => require("./LoaderTargetPlugin"), - "MemoryOutputFileSystem": () => require("./MemoryOutputFileSystem"), - "ModuleFilenameHelpers": () => require("./ModuleFilenameHelpers"), - "NamedChunksPlugin": () => require("./NamedChunksPlugin"), - "NamedModulesPlugin": () => require("./NamedModulesPlugin"), - "NoEmitOnErrorsPlugin": () => require("./NoEmitOnErrorsPlugin"), - "NormalModuleReplacementPlugin": () => require("./NormalModuleReplacementPlugin"), - "PrefetchPlugin": () => require("./PrefetchPlugin"), - "ProgressPlugin": () => require("./ProgressPlugin"), - "ProvidePlugin": () => require("./ProvidePlugin"), - "SetVarMainTemplatePlugin": () => require("./SetVarMainTemplatePlugin"), - "SingleEntryPlugin": () => require("./SingleEntryPlugin"), - "SourceMapDevToolPlugin": () => require("./SourceMapDevToolPlugin"), - "Stats": () => require("./Stats"), - "UmdMainTemplatePlugin": () => require("./UmdMainTemplatePlugin"), - "WatchIgnorePlugin": () => require("./WatchIgnorePlugin"), + AutomaticPrefetchPlugin: () => require("./AutomaticPrefetchPlugin"), + BannerPlugin: () => require("./BannerPlugin"), + CachePlugin: () => require("./CachePlugin"), + ContextExclusionPlugin: () => require("./ContextExclusionPlugin"), + ContextReplacementPlugin: () => require("./ContextReplacementPlugin"), + DefinePlugin: () => require("./DefinePlugin"), + DllPlugin: () => require("./DllPlugin"), + DllReferencePlugin: () => require("./DllReferencePlugin"), + EnvironmentPlugin: () => require("./EnvironmentPlugin"), + EvalDevToolModulePlugin: () => require("./EvalDevToolModulePlugin"), + EvalSourceMapDevToolPlugin: () => require("./EvalSourceMapDevToolPlugin"), + ExtendedAPIPlugin: () => require("./ExtendedAPIPlugin"), + ExternalsPlugin: () => require("./ExternalsPlugin"), + HashedModuleIdsPlugin: () => require("./HashedModuleIdsPlugin"), + HotModuleReplacementPlugin: () => require("./HotModuleReplacementPlugin"), + IgnorePlugin: () => require("./IgnorePlugin"), + LibraryTemplatePlugin: () => require("./LibraryTemplatePlugin"), + LoaderOptionsPlugin: () => require("./LoaderOptionsPlugin"), + LoaderTargetPlugin: () => require("./LoaderTargetPlugin"), + MemoryOutputFileSystem: () => require("./MemoryOutputFileSystem"), + ModuleFilenameHelpers: () => require("./ModuleFilenameHelpers"), + NamedChunksPlugin: () => require("./NamedChunksPlugin"), + NamedModulesPlugin: () => require("./NamedModulesPlugin"), + NoEmitOnErrorsPlugin: () => require("./NoEmitOnErrorsPlugin"), + NormalModuleReplacementPlugin: () => + require("./NormalModuleReplacementPlugin"), + PrefetchPlugin: () => require("./PrefetchPlugin"), + ProgressPlugin: () => require("./ProgressPlugin"), + ProvidePlugin: () => require("./ProvidePlugin"), + SetVarMainTemplatePlugin: () => require("./SetVarMainTemplatePlugin"), + SingleEntryPlugin: () => require("./SingleEntryPlugin"), + SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"), + Stats: () => require("./Stats"), + UmdMainTemplatePlugin: () => require("./UmdMainTemplatePlugin"), + WatchIgnorePlugin: () => require("./WatchIgnorePlugin") }); -exportPlugins(exports.optimize = {}, { - "AggressiveMergingPlugin": () => require("./optimize/AggressiveMergingPlugin"), - "AggressiveSplittingPlugin": () => require("./optimize/AggressiveSplittingPlugin"), - "ChunkModuleIdRangePlugin": () => require("./optimize/ChunkModuleIdRangePlugin"), - "LimitChunkCountPlugin": () => require("./optimize/LimitChunkCountPlugin"), - "MinChunkSizePlugin": () => require("./optimize/MinChunkSizePlugin"), - "ModuleConcatenationPlugin": () => require("./optimize/ModuleConcatenationPlugin"), - "OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin"), - "RuntimeChunkPlugin": () => require("./optimize/RuntimeChunkPlugin"), - "SideEffectsFlagPlugin": () => require("./optimize/SideEffectsFlagPlugin"), - "SplitChunksPlugin": () => require("./optimize/SplitChunksPlugin"), +exportPlugins((exports.optimize = {}), { + AggressiveMergingPlugin: () => require("./optimize/AggressiveMergingPlugin"), + AggressiveSplittingPlugin: () => + require("./optimize/AggressiveSplittingPlugin"), + ChunkModuleIdRangePlugin: () => + require("./optimize/ChunkModuleIdRangePlugin"), + LimitChunkCountPlugin: () => require("./optimize/LimitChunkCountPlugin"), + MinChunkSizePlugin: () => require("./optimize/MinChunkSizePlugin"), + ModuleConcatenationPlugin: () => + require("./optimize/ModuleConcatenationPlugin"), + OccurrenceOrderPlugin: () => require("./optimize/OccurrenceOrderPlugin"), + RuntimeChunkPlugin: () => require("./optimize/RuntimeChunkPlugin"), + SideEffectsFlagPlugin: () => require("./optimize/SideEffectsFlagPlugin"), + SplitChunksPlugin: () => require("./optimize/SplitChunksPlugin") }); -exportPlugins(exports.web = {}, { - "FetchCompileWasmTemplatePlugin": () => require("./web/FetchCompileWasmTemplatePlugin"), - "JsonpTemplatePlugin": () => require("./web/JsonpTemplatePlugin"), +exportPlugins((exports.web = {}), { + FetchCompileWasmTemplatePlugin: () => + require("./web/FetchCompileWasmTemplatePlugin"), + JsonpTemplatePlugin: () => require("./web/JsonpTemplatePlugin") }); -exportPlugins(exports.webworker = {}, { - "WebWorkerTemplatePlugin": () => require("./webworker/WebWorkerTemplatePlugin"), +exportPlugins((exports.webworker = {}), { + WebWorkerTemplatePlugin: () => require("./webworker/WebWorkerTemplatePlugin") }); -exportPlugins(exports.node = {}, { - "NodeTemplatePlugin": () => require("./node/NodeTemplatePlugin"), - "ReadFileCompileWasmTemplatePlugin": () => require("./node/ReadFileCompileWasmTemplatePlugin"), +exportPlugins((exports.node = {}), { + NodeTemplatePlugin: () => require("./node/NodeTemplatePlugin"), + ReadFileCompileWasmTemplatePlugin: () => + require("./node/ReadFileCompileWasmTemplatePlugin") }); -exportPlugins(exports.debug = {}, { - "ProfilingPlugin": () => require("./debug/ProfilingPlugin"), +exportPlugins((exports.debug = {}), { + ProfilingPlugin: () => require("./debug/ProfilingPlugin") }); const defineMissingPluginError = (namespace, pluginName, errorMessage) => { diff --git a/lib/webpack.web.js b/lib/webpack.web.js index c10ca5e67..365aa06ad 100644 --- a/lib/webpack.web.js +++ b/lib/webpack.web.js @@ -14,8 +14,11 @@ function webpack(options, callback) { const compiler = new Compiler(); compiler.options = new WebpackOptionsApply().process(options, compiler); - new WebEnvironmentPlugin(options.inputFileSystem, options.outputFileSystem).apply(compiler); - if(callback) { + new WebEnvironmentPlugin( + options.inputFileSystem, + options.outputFileSystem + ).apply(compiler); + if (callback) { compiler.run(callback); } return compiler; diff --git a/lib/webworker/WebWorkerChunkTemplatePlugin.js b/lib/webworker/WebWorkerChunkTemplatePlugin.js index 2bd0c417a..7699c8298 100644 --- a/lib/webworker/WebWorkerChunkTemplatePlugin.js +++ b/lib/webworker/WebWorkerChunkTemplatePlugin.js @@ -7,17 +7,23 @@ const ConcatSource = require("webpack-sources").ConcatSource; class WebWorkerChunkTemplatePlugin { - apply(chunkTemplate) { - chunkTemplate.hooks.render.tap("WebWorkerChunkTemplatePlugin", (modules, chunk) => { - const chunkCallbackName = chunkTemplate.outputOptions.chunkCallbackName; - const globalObject = chunkTemplate.outputOptions.globalObject; - const source = new ConcatSource(); - source.add(`${globalObject}[${JSON.stringify(chunkCallbackName)}](${JSON.stringify(chunk.ids)},`); - source.add(modules); - source.add(")"); - return source; - }); + chunkTemplate.hooks.render.tap( + "WebWorkerChunkTemplatePlugin", + (modules, chunk) => { + const chunkCallbackName = chunkTemplate.outputOptions.chunkCallbackName; + const globalObject = chunkTemplate.outputOptions.globalObject; + const source = new ConcatSource(); + source.add( + `${globalObject}[${JSON.stringify( + chunkCallbackName + )}](${JSON.stringify(chunk.ids)},` + ); + source.add(modules); + source.add(")"); + return source; + } + ); chunkTemplate.hooks.hash.tap("WebWorkerChunkTemplatePlugin", hash => { hash.update("webworker"); hash.update("3"); diff --git a/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js b/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js index 294e30788..6977ba0fd 100644 --- a/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +++ b/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js @@ -6,23 +6,35 @@ const ConcatSource = require("webpack-sources").ConcatSource; class WebWorkerHotUpdateChunkTemplatePlugin { - apply(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.hooks.render.tap("WebWorkerHotUpdateChunkTemplatePlugin", (modulesSource, modules, removedModules, hash, id) => { - const hotUpdateFunction = hotUpdateChunkTemplate.outputOptions.hotUpdateFunction; - const globalObject = hotUpdateChunkTemplate.outputOptions.globalObject; - const source = new ConcatSource(); - source.add(`${globalObject}[${JSON.stringify(hotUpdateFunction)}](${JSON.stringify(id)},`); - source.add(modulesSource); - source.add(")"); - return source; - }); - hotUpdateChunkTemplate.hooks.hash.tap("WebWorkerHotUpdateChunkTemplatePlugin", hash => { - hash.update("WebWorkerHotUpdateChunkTemplatePlugin"); - hash.update("3"); - hash.update(hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + ""); - hash.update(hotUpdateChunkTemplate.outputOptions.globalObject + ""); - }); + hotUpdateChunkTemplate.hooks.render.tap( + "WebWorkerHotUpdateChunkTemplatePlugin", + (modulesSource, modules, removedModules, hash, id) => { + const hotUpdateFunction = + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction; + const globalObject = hotUpdateChunkTemplate.outputOptions.globalObject; + const source = new ConcatSource(); + source.add( + `${globalObject}[${JSON.stringify( + hotUpdateFunction + )}](${JSON.stringify(id)},` + ); + source.add(modulesSource); + source.add(")"); + return source; + } + ); + hotUpdateChunkTemplate.hooks.hash.tap( + "WebWorkerHotUpdateChunkTemplatePlugin", + hash => { + hash.update("WebWorkerHotUpdateChunkTemplatePlugin"); + hash.update("3"); + hash.update( + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + "" + ); + hash.update(hotUpdateChunkTemplate.outputOptions.globalObject + ""); + } + ); } } module.exports = WebWorkerHotUpdateChunkTemplatePlugin; diff --git a/lib/webworker/WebWorkerMainTemplate.runtime.js b/lib/webworker/WebWorkerMainTemplate.runtime.js index bc801c390..405f2d9cb 100644 --- a/lib/webworker/WebWorkerMainTemplate.runtime.js +++ b/lib/webworker/WebWorkerMainTemplate.runtime.js @@ -4,19 +4,22 @@ */ /*globals installedChunks hotAddUpdateChunk parentHotUpdateCallback importScripts XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ */ module.exports = function() { - function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars + function webpackHotUpdateCallback(chunkId, moreModules) { + // eslint-disable-line no-unused-vars hotAddUpdateChunk(chunkId, moreModules); - if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); + if (parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); } //$semicolon - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + // eslint-disable-line no-unused-vars importScripts($require$.p + $hotChunkFilename$); } - function hotDownloadManifest(requestTimeout) { // eslint-disable-line no-unused-vars + function hotDownloadManifest(requestTimeout) { + // eslint-disable-line no-unused-vars requestTimeout = requestTimeout || 10000; return new Promise(function(resolve, reject) { - if(typeof XMLHttpRequest === "undefined") + if (typeof XMLHttpRequest === "undefined") return reject(new Error("No browser support")); try { var request = new XMLHttpRequest(); @@ -24,25 +27,27 @@ module.exports = function() { request.open("GET", requestPath, true); request.timeout = requestTimeout; request.send(null); - } catch(err) { + } catch (err) { return reject(err); } request.onreadystatechange = function() { - if(request.readyState !== 4) return; - if(request.status === 0) { + if (request.readyState !== 4) return; + if (request.status === 0) { // timeout - reject(new Error("Manifest request to " + requestPath + " timed out.")); - } else if(request.status === 404) { + reject( + new Error("Manifest request to " + requestPath + " timed out.") + ); + } else if (request.status === 404) { // no update available resolve(); - } else if(request.status !== 200 && request.status !== 304) { + } else if (request.status !== 200 && request.status !== 304) { // other failure reject(new Error("Manifest request to " + requestPath + " failed.")); } else { // success try { var update = JSON.parse(request.responseText); - } catch(e) { + } catch (e) { reject(e); return; } @@ -52,7 +57,8 @@ module.exports = function() { }); } - function hotDisposeChunk(chunkId) { //eslint-disable-line no-unused-vars + function hotDisposeChunk(chunkId) { + //eslint-disable-line no-unused-vars delete installedChunks[chunkId]; } }; diff --git a/lib/webworker/WebWorkerMainTemplatePlugin.js b/lib/webworker/WebWorkerMainTemplatePlugin.js index 4132d7140..aee10e38f 100644 --- a/lib/webworker/WebWorkerMainTemplatePlugin.js +++ b/lib/webworker/WebWorkerMainTemplatePlugin.js @@ -9,95 +9,137 @@ const Template = require("../Template"); class WebWorkerMainTemplatePlugin { apply(mainTemplate) { const needChunkOnDemandLoadingCode = chunk => { - for(const chunkGroup of chunk.groupsIterable) { - if(chunkGroup.getNumberOfChildren() > 0) return true; + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.getNumberOfChildren() > 0) return true; } return false; }; - mainTemplate.hooks.localVars.tap("WebWorkerMainTemplatePlugin", (source, chunk) => { - if(needChunkOnDemandLoadingCode(chunk)) { - return Template.asString([ - source, - "", - "// object to store loaded chunks", - "// \"1\" means \"already loaded\"", - "var installedChunks = {", - Template.indent( - chunk.ids.map((id) => `${id}: 1`).join(",\n") - ), - "};" - ]); - } - return source; - }); - mainTemplate.hooks.requireEnsure.tap("WebWorkerMainTemplatePlugin", (_, chunk, hash) => { - const chunkFilename = mainTemplate.outputOptions.chunkFilename; - return Template.asString([ - "promises.push(Promise.resolve().then(function() {", - Template.indent([ - "// \"1\" is the signal for \"already loaded\"", - "if(!installedChunks[chunkId]) {", - Template.indent([ - "importScripts(" + - mainTemplate.getAssetPath(JSON.stringify(chunkFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"" - } - }) + ");" - ]), - "}", - ]), - "}));" - ]); - }); - mainTemplate.hooks.bootstrap.tap("WebWorkerMainTemplatePlugin", (source, chunk, hash) => { - if(needChunkOnDemandLoadingCode(chunk)) { - const chunkCallbackName = mainTemplate.outputOptions.chunkCallbackName; - const globalObject = mainTemplate.outputOptions.globalObject; - return Template.asString([ - source, - `${globalObject}[${JSON.stringify(chunkCallbackName)}] = function webpackChunkCallback(chunkIds, moreModules) {`, - Template.indent([ - "for(var moduleId in moreModules) {", - Template.indent(mainTemplate.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")), - "}", - "while(chunkIds.length)", - Template.indent("installedChunks[chunkIds.pop()] = 1;") - ]), - "};" - ]); - } - return source; - }); - mainTemplate.hooks.hotBootstrap.tap("WebWorkerMainTemplatePlugin", (source, chunk, hash) => { - const hotUpdateChunkFilename = mainTemplate.outputOptions.hotUpdateChunkFilename; - const hotUpdateMainFilename = mainTemplate.outputOptions.hotUpdateMainFilename; - const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction; - const globalObject = mainTemplate.outputOptions.globalObject; - const currentHotUpdateChunkFilename = mainTemplate.getAssetPath(JSON.stringify(hotUpdateChunkFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"" + mainTemplate.hooks.localVars.tap( + "WebWorkerMainTemplatePlugin", + (source, chunk) => { + if (needChunkOnDemandLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// object to store loaded chunks", + '// "1" means "already loaded"', + "var installedChunks = {", + Template.indent(chunk.ids.map(id => `${id}: 1`).join(",\n")), + "};" + ]); } - }); - const currentHotUpdateMainFilename = mainTemplate.getAssetPath(JSON.stringify(hotUpdateMainFilename), { - hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, - }); + return source; + } + ); + mainTemplate.hooks.requireEnsure.tap( + "WebWorkerMainTemplatePlugin", + (_, chunk, hash) => { + const chunkFilename = mainTemplate.outputOptions.chunkFilename; + return Template.asString([ + "promises.push(Promise.resolve().then(function() {", + Template.indent([ + '// "1" is the signal for "already loaded"', + "if(!installedChunks[chunkId]) {", + Template.indent([ + "importScripts(" + + mainTemplate.getAssetPath(JSON.stringify(chunkFilename), { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode( + hash, + length + )} + "`, + chunk: { + id: '" + chunkId + "' + } + }) + + ");" + ]), + "}" + ]), + "}));" + ]); + } + ); + mainTemplate.hooks.bootstrap.tap( + "WebWorkerMainTemplatePlugin", + (source, chunk, hash) => { + if (needChunkOnDemandLoadingCode(chunk)) { + const chunkCallbackName = + mainTemplate.outputOptions.chunkCallbackName; + const globalObject = mainTemplate.outputOptions.globalObject; + return Template.asString([ + source, + `${globalObject}[${JSON.stringify( + chunkCallbackName + )}] = function webpackChunkCallback(chunkIds, moreModules) {`, + Template.indent([ + "for(var moduleId in moreModules) {", + Template.indent( + mainTemplate.renderAddModule( + hash, + chunk, + "moduleId", + "moreModules[moduleId]" + ) + ), + "}", + "while(chunkIds.length)", + Template.indent("installedChunks[chunkIds.pop()] = 1;") + ]), + "};" + ]); + } + return source; + } + ); + mainTemplate.hooks.hotBootstrap.tap( + "WebWorkerMainTemplatePlugin", + (source, chunk, hash) => { + const hotUpdateChunkFilename = + mainTemplate.outputOptions.hotUpdateChunkFilename; + const hotUpdateMainFilename = + mainTemplate.outputOptions.hotUpdateMainFilename; + const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction; + const globalObject = mainTemplate.outputOptions.globalObject; + const currentHotUpdateChunkFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateChunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "' + } + } + ); + const currentHotUpdateMainFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateMainFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` + } + ); - return source + "\n" + - `var parentHotUpdateCallback = ${globalObject}[${JSON.stringify(hotUpdateFunction)}];\n` + - `${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` + - Template.getFunctionContent(require("./WebWorkerMainTemplate.runtime.js")) - .replace(/\/\/\$semicolon/g, ";") - .replace(/\$require\$/g, mainTemplate.requireFn) - .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) - .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) - .replace(/\$hash\$/g, JSON.stringify(hash)); - }); + return ( + source + + "\n" + + `var parentHotUpdateCallback = ${globalObject}[${JSON.stringify( + hotUpdateFunction + )}];\n` + + `${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` + + Template.getFunctionContent( + require("./WebWorkerMainTemplate.runtime.js") + ) + .replace(/\/\/\$semicolon/g, ";") + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) + .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) + .replace(/\$hash\$/g, JSON.stringify(hash)) + ); + } + ); mainTemplate.hooks.hash.tap("WebWorkerMainTemplatePlugin", hash => { hash.update("webworker"); hash.update("3"); diff --git a/lib/webworker/WebWorkerTemplatePlugin.js b/lib/webworker/WebWorkerTemplatePlugin.js index 996e9d0e7..5ad89f37a 100644 --- a/lib/webworker/WebWorkerTemplatePlugin.js +++ b/lib/webworker/WebWorkerTemplatePlugin.js @@ -10,11 +10,16 @@ const WebWorkerHotUpdateChunkTemplatePlugin = require("./WebWorkerHotUpdateChunk class WebWorkerTemplatePlugin { apply(compiler) { - compiler.hooks.thisCompilation.tap("WebWorkerTemplatePlugin", (compilation) => { - new WebWorkerMainTemplatePlugin().apply(compilation.mainTemplate); - new WebWorkerChunkTemplatePlugin().apply(compilation.chunkTemplate); - new WebWorkerHotUpdateChunkTemplatePlugin().apply(compilation.hotUpdateChunkTemplate); - }); + compiler.hooks.thisCompilation.tap( + "WebWorkerTemplatePlugin", + compilation => { + new WebWorkerMainTemplatePlugin().apply(compilation.mainTemplate); + new WebWorkerChunkTemplatePlugin().apply(compilation.chunkTemplate); + new WebWorkerHotUpdateChunkTemplatePlugin().apply( + compilation.hotUpdateChunkTemplate + ); + } + ); } } module.exports = WebWorkerTemplatePlugin; diff --git a/test/BenchmarkTestCases.benchmark.js b/test/BenchmarkTestCases.benchmark.js index f626a6304..da2833143 100644 --- a/test/BenchmarkTestCases.benchmark.js +++ b/test/BenchmarkTestCases.benchmark.js @@ -11,7 +11,10 @@ const Benchmark = require("benchmark"); describe("BenchmarkTestCases", function() { const casesPath = path.join(__dirname, "benchmarkCases"); const tests = fs.readdirSync(casesPath).filter(function(folder) { - return folder.indexOf("_") < 0 && fs.existsSync(path.resolve(casesPath, folder, "webpack.config.js")); + return ( + folder.indexOf("_") < 0 && + fs.existsSync(path.resolve(casesPath, folder, "webpack.config.js")) + ); }); const baselinesPath = path.join(__dirname, "js", "benchmark-baselines"); @@ -19,51 +22,73 @@ describe("BenchmarkTestCases", function() { try { fs.mkdirSync(path.join(__dirname, "js")); - } catch(e) {} + } catch (e) {} try { fs.mkdirSync(baselinesPath); - } catch(e) {} + } catch (e) {} before(function(done) { this.timeout(270000); const git = require("simple-git"); const rootPath = path.join(__dirname, ".."); getBaselineRevs(rootPath, (err, baselineRevisions) => { - if(err) return done(err); - asyncLib.eachSeries(baselineRevisions, (baselineInfo, callback) => { - const baselineRevision = baselineInfo.rev; - const baselinePath = path.resolve(baselinesPath, baselineRevision); - if(fs.existsSync(path.resolve(baselinePath, ".git"))) { - doLoadWebpack(); - } else { - try { - fs.mkdirSync(baselinePath); - } catch(e) {} - const gitIndex = path.resolve(rootPath, ".git/index"); - const index = fs.readFileSync(gitIndex); - git(rootPath).raw(["rev-list", "-n", "1", "HEAD"], (err, prevHead) => { - if(err) return callback(err); - git(baselinePath).raw(["--git-dir", path.join(rootPath, ".git"), "reset", "--hard", baselineRevision], err => { - if(err) return callback(err); - git(rootPath).raw(["reset", "--soft", prevHead.split("\n")[0]], err => { - if(err) return callback(err); - fs.writeFileSync(gitIndex, index); - doLoadWebpack(); - }); - }); - }); - } + if (err) return done(err); + asyncLib.eachSeries( + baselineRevisions, + (baselineInfo, callback) => { + const baselineRevision = baselineInfo.rev; + const baselinePath = path.resolve(baselinesPath, baselineRevision); + if (fs.existsSync(path.resolve(baselinePath, ".git"))) { + doLoadWebpack(); + } else { + try { + fs.mkdirSync(baselinePath); + } catch (e) {} + const gitIndex = path.resolve(rootPath, ".git/index"); + const index = fs.readFileSync(gitIndex); + git(rootPath).raw( + ["rev-list", "-n", "1", "HEAD"], + (err, prevHead) => { + if (err) return callback(err); + git(baselinePath).raw( + [ + "--git-dir", + path.join(rootPath, ".git"), + "reset", + "--hard", + baselineRevision + ], + err => { + if (err) return callback(err); + git(rootPath).raw( + ["reset", "--soft", prevHead.split("\n")[0]], + err => { + if (err) return callback(err); + fs.writeFileSync(gitIndex, index); + doLoadWebpack(); + } + ); + } + ); + } + ); + } - function doLoadWebpack() { - const baselineWebpack = require(path.resolve(baselinePath, "lib/webpack.js")); - baselines.push({ - name: baselineInfo.name, - rev: baselineRevision, - webpack: baselineWebpack - }); - callback(); - } - }, done); + function doLoadWebpack() { + const baselineWebpack = require(path.resolve( + baselinePath, + "lib/webpack.js" + )); + baselines.push({ + name: baselineInfo.name, + rev: baselineRevision, + webpack: baselineWebpack + }); + callback(); + } + }, + done + ); }); }); @@ -71,53 +96,116 @@ describe("BenchmarkTestCases", function() { const git = require("simple-git")(rootPath); const lastVersionTag = "v" + require("../package.json").version; git.raw(["rev-list", "-n", "1", lastVersionTag], (err, resultVersion) => { - if(err) return callback(err); + if (err) return callback(err); const matchVersion = /^([a-f0-9]+)\s*$/.exec(resultVersion); - if(!matchVersion) return callback(new Error("Invalid result from git revparse")); + if (!matchVersion) + return callback(new Error("Invalid result from git revparse")); const revLastVersion = matchVersion[1]; - git.raw(["rev-list", "--parents", "-n", "1", "HEAD"], (err, resultParents) => { - if(err) return callback(err); - const match = /^([a-f0-9]+)\s*([a-f0-9]+)\s*([a-f0-9]+)?\s*$/.exec(resultParents); - if(!match) return callback(new Error("Invalid result from git rev-list")); - const head = match[1]; - const parent1 = match[2]; - const parent2 = match[3]; - if(parent2 && parent1) { - return callback(null, [{ - name: "HEAD", - rev: head - }, head !== revLastVersion && { - name: lastVersionTag, - rev: revLastVersion - }, parent1 !== revLastVersion && head !== revLastVersion && { - name: "base", - rev: parent1 - }].filter(Boolean)); - } else if(parent1) { - return callback(null, [{ - name: "HEAD", - rev: head - }, head !== revLastVersion && { - name: lastVersionTag, - rev: revLastVersion - }].filter(Boolean)); - } else { - return callback(new Error("No baseline found")); + git.raw( + ["rev-list", "--parents", "-n", "1", "HEAD"], + (err, resultParents) => { + if (err) return callback(err); + const match = /^([a-f0-9]+)\s*([a-f0-9]+)\s*([a-f0-9]+)?\s*$/.exec( + resultParents + ); + if (!match) + return callback(new Error("Invalid result from git rev-list")); + const head = match[1]; + const parent1 = match[2]; + const parent2 = match[3]; + if (parent2 && parent1) { + return callback( + null, + [ + { + name: "HEAD", + rev: head + }, + head !== revLastVersion && { + name: lastVersionTag, + rev: revLastVersion + }, + parent1 !== revLastVersion && + head !== revLastVersion && { + name: "base", + rev: parent1 + } + ].filter(Boolean) + ); + } else if (parent1) { + return callback( + null, + [ + { + name: "HEAD", + rev: head + }, + head !== revLastVersion && { + name: lastVersionTag, + rev: revLastVersion + } + ].filter(Boolean) + ); + } else { + return callback(new Error("No baseline found")); + } } - }); + ); }); } function tDistribution(n) { // two-sided, 90% // https://en.wikipedia.org/wiki/Student%27s_t-distribution - if(n <= 30) { + if (n <= 30) { // 1 2 ... - const data = [6.314, 2.920, 2.353, 2.132, 2.015, 1.943, 1.895, 1.860, 1.833, 1.812, 1.796, 1.782, 1.771, 1.761, 1.753, 1.746, 1.740, 1.734, 1.729, 1.725, 1.721, 1.717, 1.714, 1.711, 1.708, 1.706, 1.703, 1.701, 1.699, 1.697]; + const data = [ + 6.314, + 2.92, + 2.353, + 2.132, + 2.015, + 1.943, + 1.895, + 1.86, + 1.833, + 1.812, + 1.796, + 1.782, + 1.771, + 1.761, + 1.753, + 1.746, + 1.74, + 1.734, + 1.729, + 1.725, + 1.721, + 1.717, + 1.714, + 1.711, + 1.708, + 1.706, + 1.703, + 1.701, + 1.699, + 1.697 + ]; return data[n - 1]; - } else if(n <= 120) { + } else if (n <= 120) { // 30 40 50 60 70 80 90 100 110 120 - const data = [1.697, 1.684, 1.676, 1.671, 1.667, 1.664, 1.662, 1.660, 1.659, 1.658]; + const data = [ + 1.697, + 1.684, + 1.676, + 1.671, + 1.667, + 1.664, + 1.662, + 1.66, + 1.659, + 1.658 + ]; var a = data[Math.floor(n / 10) - 3]; var b = data[Math.ceil(n / 10) - 3]; var f = n / 10 - Math.floor(n / 10); @@ -131,35 +219,42 @@ describe("BenchmarkTestCases", function() { // warmup const warmupCompiler = webpack(config, (err, stats) => { warmupCompiler.purgeInputFileSystem(); - const bench = new Benchmark(function(deferred) { - const compiler = webpack(config, (err, stats) => { - compiler.purgeInputFileSystem(); - if(err) { - callback(err); - return; - } - if(stats.hasErrors()) { - callback(new Error(stats.toJson().errors.join("\n\n"))); - return; - } - deferred.resolve(); - }); - }, { - maxTime: 30, - defer: true, - initCount: 1, - onComplete: function() { - const stats = bench.stats; - const n = stats.sample.length; - const nSqrt = Math.sqrt(n); - const z = tDistribution(n - 1); - stats.minConfidence = stats.mean - z * stats.deviation / nSqrt; - stats.maxConfidence = stats.mean + z * stats.deviation / nSqrt; - stats.text = `${Math.round(stats.mean * 1000)}ms ± ${Math.round(stats.deviation * 1000)}ms [${Math.round(stats.minConfidence * 1000)}ms; ${Math.round(stats.maxConfidence * 1000)}ms]`; - callback(null, bench.stats); + const bench = new Benchmark( + function(deferred) { + const compiler = webpack(config, (err, stats) => { + compiler.purgeInputFileSystem(); + if (err) { + callback(err); + return; + } + if (stats.hasErrors()) { + callback(new Error(stats.toJson().errors.join("\n\n"))); + return; + } + deferred.resolve(); + }); }, - onError: callback - }); + { + maxTime: 30, + defer: true, + initCount: 1, + onComplete: function() { + const stats = bench.stats; + const n = stats.sample.length; + const nSqrt = Math.sqrt(n); + const z = tDistribution(n - 1); + stats.minConfidence = stats.mean - z * stats.deviation / nSqrt; + stats.maxConfidence = stats.mean + z * stats.deviation / nSqrt; + stats.text = `${Math.round(stats.mean * 1000)}ms ± ${Math.round( + stats.deviation * 1000 + )}ms [${Math.round(stats.minConfidence * 1000)}ms; ${Math.round( + stats.maxConfidence * 1000 + )}ms]`; + callback(null, bench.stats); + }, + onError: callback + } + ); bench.run({ async: true }); @@ -178,30 +273,48 @@ describe("BenchmarkTestCases", function() { const test = new Test(title, fn); suite.addTest(test); } - it(`should benchmark ${baseline.name} (${baseline.rev})`, function(done) { + it(`should benchmark ${baseline.name} (${baseline.rev})`, function( + done + ) { this.timeout(180000); - const outputDirectory = path.join(__dirname, "js", "benchmark", `baseline-${baseline.name}`, testName); - const config = Object.create(require(path.join(testDirectory, "webpack.config.js"))); + const outputDirectory = path.join( + __dirname, + "js", + "benchmark", + `baseline-${baseline.name}`, + testName + ); + const config = Object.create( + require(path.join(testDirectory, "webpack.config.js")) + ); config.output = Object.create(config.output || {}); - if(!config.context) config.context = testDirectory; - if(!config.output.path) config.output.path = outputDirectory; + if (!config.context) config.context = testDirectory; + if (!config.output.path) config.output.path = outputDirectory; runBenchmark(baseline.webpack, config, (err, stats) => { - if(err) return done(err); + if (err) return done(err); console.log(` ${baseline.name} ${stats.text}`); - if(baseline.name === "HEAD") - headStats = stats; - else - baselineStats = stats; + if (baseline.name === "HEAD") headStats = stats; + else baselineStats = stats; done(); }); }); - if(baseline.name !== "HEAD") { - it(`HEAD should not be slower than ${baseline.name} (${baseline.rev})`, function() { - if(baselineStats.maxConfidence < headStats.minConfidence) { - throw new Error(`HEAD (${headStats.text}) is slower than ${baseline.name} (${baselineStats.text}) (90% confidence)`); - } else if(baselineStats.minConfidence > headStats.maxConfidence) { - console.log(`======> HEAD is ${Math.round(baselineStats.mean / headStats.mean * 100 - 100)}% faster than ${baseline.name} (90% confidence)!`); + if (baseline.name !== "HEAD") { + it(`HEAD should not be slower than ${baseline.name} (${ + baseline.rev + })`, function() { + if (baselineStats.maxConfidence < headStats.minConfidence) { + throw new Error( + `HEAD (${headStats.text}) is slower than ${baseline.name} (${ + baselineStats.text + }) (90% confidence)` + ); + } else if (baselineStats.minConfidence > headStats.maxConfidence) { + console.log( + `======> HEAD is ${Math.round( + baselineStats.mean / headStats.mean * 100 - 100 + )}% faster than ${baseline.name} (90% confidence)!` + ); } }); } diff --git a/test/CachePlugin.unittest.js b/test/CachePlugin.unittest.js index a91ddf473..7ce741c01 100644 --- a/test/CachePlugin.unittest.js +++ b/test/CachePlugin.unittest.js @@ -16,7 +16,7 @@ describe("CachePlugin", () => { }); describe("applyMtime", () => { - beforeEach(() => env.plugin = new CachePlugin()); + beforeEach(() => (env.plugin = new CachePlugin())); it("sets file system accuracy to 1 for granular modification timestamp", () => { env.plugin.applyMtime(1483819067001); diff --git a/test/CaseSensitiveModulesWarning.unittest.js b/test/CaseSensitiveModulesWarning.unittest.js index ab0690941..6023c02ec 100644 --- a/test/CaseSensitiveModulesWarning.unittest.js +++ b/test/CaseSensitiveModulesWarning.unittest.js @@ -4,11 +4,13 @@ require("should"); const CaseSensitiveModulesWarning = require("../lib/CaseSensitiveModulesWarning"); const createModule = function(identifier, numberOfReasons) { - const reasons = new Array(numberOfReasons || 0).fill(null).map((value, index) => { - return { - module: createModule(`${identifier}-reason-${index}`) - }; - }); + const reasons = new Array(numberOfReasons || 0) + .fill(null) + .map((value, index) => { + return { + module: createModule(`${identifier}-reason-${index}`) + }; + }); return { identifier: () => identifier, @@ -29,10 +31,14 @@ describe("CaseSensitiveModulesWarning", () => { myCaseSensitiveModulesWarning = new CaseSensitiveModulesWarning(modules); }); - it("has the a name", () => myCaseSensitiveModulesWarning.name.should.be.exactly("CaseSensitiveModulesWarning")); + it("has the a name", () => + myCaseSensitiveModulesWarning.name.should.be.exactly( + "CaseSensitiveModulesWarning" + )); it("has the a message", () => { - myCaseSensitiveModulesWarning.message.should.be.exactly(` + myCaseSensitiveModulesWarning.message.should.be.exactly( + ` There are multiple modules with names that only differ in casing. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic. Use equal casing. Compare these module identifiers: @@ -43,7 +49,8 @@ Use equal casing. Compare these module identifiers: * foobar Used by 2 module(s), i. e. foobar-reason-0 -`.trim()); +`.trim() + ); }); it("has the an origin", () => diff --git a/test/Chunk.unittest.js b/test/Chunk.unittest.js index 317ec5973..42c5c26fc 100644 --- a/test/Chunk.unittest.js +++ b/test/Chunk.unittest.js @@ -8,13 +8,18 @@ const Chunk = require("../lib/Chunk"); describe("Chunk", () => { let ChunkInstance; - beforeEach(() => ChunkInstance = new Chunk("chunk-test", "module-test", "loc-test")); + beforeEach( + () => (ChunkInstance = new Chunk("chunk-test", "module-test", "loc-test")) + ); - it("should have debugId more than 999", () => should(ChunkInstance.debugId).be.above(999)); + it("should have debugId more than 999", () => + should(ChunkInstance.debugId).be.above(999)); - it("returns a string with modules information", () => should(ChunkInstance.toString()).be.exactly("Chunk[]")); + it("returns a string with modules information", () => + should(ChunkInstance.toString()).be.exactly("Chunk[]")); - it("should not be the initial instance", () => should(ChunkInstance.canBeInitial()).be.false()); + it("should not be the initial instance", () => + should(ChunkInstance.canBeInitial()).be.false()); describe("entry", () => { it("returns an error if get entry", () => @@ -45,15 +50,18 @@ describe("Chunk", () => { }); describe("isEmpty", () => { - it("should NOT have any module by default", () => should(ChunkInstance.isEmpty()).be.true()); + it("should NOT have any module by default", () => + should(ChunkInstance.isEmpty()).be.true()); }); describe("size", () => { it("should NOT have any module by default", () => - should(ChunkInstance.size({ - chunkOverhead: 10, - entryChunkMultiplicator: 2 - })).be.exactly(10)); + should( + ChunkInstance.size({ + chunkOverhead: 10, + entryChunkMultiplicator: 2 + }) + ).be.exactly(10)); }); describe("removeModule", function() { diff --git a/test/Compiler-caching.test.js b/test/Compiler-caching.test.js index c92e412ec..9e612c848 100644 --- a/test/Compiler-caching.test.js +++ b/test/Compiler-caching.test.js @@ -23,7 +23,7 @@ describe("Compiler (caching)", function() { options.output.pathinfo = true; const logs = { mkdirp: [], - writeFile: [], + writeFile: [] }; const c = webpack(options); @@ -42,17 +42,20 @@ describe("Compiler (caching)", function() { callback(); } }; - c.hooks.compilation.tap("CompilerCachingTest", (compilation) => compilation.bail = true); + c.hooks.compilation.tap( + "CompilerCachingTest", + compilation => (compilation.bail = true) + ); let compilerIteration = 1; function runCompiler(options, callback) { - if(typeof options === "function") { + if (typeof options === "function") { callback = options; options = {}; } c.run((err, stats) => { - if(err) throw err; + if (err) throw err; should.strictEqual(typeof stats, "object"); stats = stats.toJson({ modules: true, @@ -61,10 +64,10 @@ describe("Compiler (caching)", function() { should.strictEqual(typeof stats, "object"); stats.should.have.property("errors"); Array.isArray(stats.errors).should.be.ok(); - if(options.expectErrors) { + if (options.expectErrors) { stats.errors.length.should.be.eql(options.expectErrors); } else { - if(stats.errors.length > 0) { + if (stats.errors.length > 0) { stats.errors[0].should.be.type("string"); throw new Error(stats.errors[0]); } @@ -82,7 +85,11 @@ describe("Compiler (caching)", function() { }; } - const tempFixturePath = path.join(__dirname, "fixtures", "temp-cache-fixture"); + const tempFixturePath = path.join( + __dirname, + "fixtures", + "temp-cache-fixture" + ); const aFilepath = path.join(tempFixturePath, "a.js"); const cFilepath = path.join(tempFixturePath, "c.js"); @@ -90,8 +97,8 @@ describe("Compiler (caching)", function() { function ignoreENOENT(fn) { try { return fn(); - } catch(e) { - if(e.code !== "ENOENT") { + } catch (e) { + if (e.code !== "ENOENT") { throw e; } } @@ -104,24 +111,27 @@ describe("Compiler (caching)", function() { after(cleanup); function createTempFixture() { - // Remove previous copy if present try { - if(fs.statSync(tempFixturePath)) { + if (fs.statSync(tempFixturePath)) { fs.unlinkSync(aFilepath); fs.unlinkSync(cFilepath); fs.rmdirSync(tempFixturePath); } - } catch(e) { - if(e.code !== "ENOENT") { + } catch (e) { + if (e.code !== "ENOENT") { throw e; } } // Copy over file since we"ll be modifying some of them fs.mkdirSync(tempFixturePath); - fs.createReadStream(path.join(__dirname, "fixtures", "a.js")).pipe(fs.createWriteStream(aFilepath)); - fs.createReadStream(path.join(__dirname, "fixtures", "c.js")).pipe(fs.createWriteStream(cFilepath)); + fs + .createReadStream(path.join(__dirname, "fixtures", "a.js")) + .pipe(fs.createWriteStream(aFilepath)); + fs + .createReadStream(path.join(__dirname, "fixtures", "c.js")) + .pipe(fs.createWriteStream(cFilepath)); return { rootPath: tempFixturePath, @@ -130,95 +140,167 @@ describe("Compiler (caching)", function() { }; } - it("should cache single file (with manual 1s wait) ", (done) => { - + it("should cache single file (with manual 1s wait) ", done => { const options = {}; const tempFixture = createTempFixture(); - const helper = compile("./temp-cache-fixture/c", options, (stats, files) => { - - // Not cached the first time - stats.assets[0].name.should.be.exactly("bundle.js"); - stats.assets[0].emitted.should.be.exactly(true); - - helper.runAgain((stats, files, iteration) => { - - // Cached the second run + const helper = compile( + "./temp-cache-fixture/c", + options, + (stats, files) => { + // Not cached the first time stats.assets[0].name.should.be.exactly("bundle.js"); - stats.assets[0].emitted.should.be.exactly(false); + stats.assets[0].emitted.should.be.exactly(true); - const aContent = fs.readFileSync(tempFixture.aFilepath).toString().replace("This is a", "This is a MODIFIED"); + helper.runAgain((stats, files, iteration) => { + // Cached the second run + stats.assets[0].name.should.be.exactly("bundle.js"); + stats.assets[0].emitted.should.be.exactly(false); + + const aContent = fs + .readFileSync(tempFixture.aFilepath) + .toString() + .replace("This is a", "This is a MODIFIED"); + + setTimeout(() => { + fs.writeFileSync(tempFixture.aFilepath, aContent); + + helper.runAgain((stats, files, iteration) => { + // Cached the third run + stats.assets[0].name.should.be.exactly("bundle.js"); + stats.assets[0].emitted.should.be.exactly(true); + + done(); + }); + }, 1100); + }); + } + ); + }); + + it("should cache single file (even with no timeout) ", done => { + const options = {}; + const tempFixture = createTempFixture(); + + const helper = compile( + "./temp-cache-fixture/c", + options, + (stats, files) => { + // Not cached the first time + stats.assets[0].name.should.be.exactly("bundle.js"); + stats.assets[0].emitted.should.be.exactly(true); + + helper.runAgain((stats, files, iteration) => { + // Cached the second run + stats.assets[0].name.should.be.exactly("bundle.js"); + stats.assets[0].emitted.should.be.exactly(false); + + files["/bundle.js"].should.containEql("This is a"); + + const aContent = fs + .readFileSync(tempFixture.aFilepath) + .toString() + .replace("This is a", "This is a MODIFIED"); - setTimeout(() => { fs.writeFileSync(tempFixture.aFilepath, aContent); helper.runAgain((stats, files, iteration) => { - // Cached the third run stats.assets[0].name.should.be.exactly("bundle.js"); stats.assets[0].emitted.should.be.exactly(true); + files["/bundle.js"].should.containEql("This is a MODIFIED"); + done(); }); - - }, 1100); - }); - }); - }); - - it("should cache single file (even with no timeout) ", (done) => { - - const options = {}; - const tempFixture = createTempFixture(); - - const helper = compile("./temp-cache-fixture/c", options, (stats, files) => { - - // Not cached the first time - stats.assets[0].name.should.be.exactly("bundle.js"); - stats.assets[0].emitted.should.be.exactly(true); - - helper.runAgain((stats, files, iteration) => { - // Cached the second run - stats.assets[0].name.should.be.exactly("bundle.js"); - stats.assets[0].emitted.should.be.exactly(false); - - files["/bundle.js"].should.containEql("This is a"); - - const aContent = fs.readFileSync(tempFixture.aFilepath).toString().replace("This is a", "This is a MODIFIED"); - - fs.writeFileSync(tempFixture.aFilepath, aContent); - - helper.runAgain((stats, files, iteration) => { - - // Cached the third run - stats.assets[0].name.should.be.exactly("bundle.js"); - stats.assets[0].emitted.should.be.exactly(true); - - files["/bundle.js"].should.containEql("This is a MODIFIED"); - - done(); }); - }); - }); + } + ); }); - it("should only build when modified (with manual 2s wait)", (done) => { - + it("should only build when modified (with manual 2s wait)", done => { const options = {}; const tempFixture = createTempFixture(); - const helper = compile("./temp-cache-fixture/c", options, (stats, files) => { + const helper = compile( + "./temp-cache-fixture/c", + options, + (stats, files) => { + // Built the first time + stats.modules[0].name.should.containEql("c.js"); + stats.modules[0].built.should.be.exactly( + true, + "c.js should have been built" + ); - // Built the first time - stats.modules[0].name.should.containEql("c.js"); - stats.modules[0].built.should.be.exactly(true, "c.js should have been built"); + stats.modules[1].name.should.containEql("a.js"); + stats.modules[1].built.should.be.exactly( + true, + "a.js should have been built" + ); - stats.modules[1].name.should.containEql("a.js"); - stats.modules[1].built.should.be.exactly(true, "a.js should have been built"); + setTimeout(() => { + helper.runAgain((stats, files, iteration) => { + // Not built when cached the second run + stats.modules[0].name.should.containEql("c.js"); + //stats.modules[0].built.should.be.exactly(false, "c.js should not have built"); + + stats.modules[1].name.should.containEql("a.js"); + //stats.modules[1].built.should.be.exactly(false, "a.js should not have built"); + + const aContent = fs + .readFileSync(tempFixture.aFilepath) + .toString() + .replace("This is a", "This is a MODIFIED"); + + setTimeout(() => { + fs.writeFileSync(tempFixture.aFilepath, aContent); + + helper.runAgain((stats, files, iteration) => { + // And only a.js built after it was modified + stats.modules[0].name.should.containEql("c.js"); + stats.modules[0].built.should.be.exactly( + false, + "c.js should not have built" + ); + + stats.modules[1].name.should.containEql("a.js"); + stats.modules[1].built.should.be.exactly( + true, + "a.js should have been built" + ); + + done(); + }); + }, 2100); + }); + }, 4100); + } + ); + }); + + it("should build when modified (even with no timeout)", done => { + const options = {}; + const tempFixture = createTempFixture(); + + const helper = compile( + "./temp-cache-fixture/c", + options, + (stats, files) => { + // Built the first time + stats.modules[0].name.should.containEql("c.js"); + stats.modules[0].built.should.be.exactly( + true, + "c.js should have been built" + ); + + stats.modules[1].name.should.containEql("a.js"); + stats.modules[1].built.should.be.exactly( + true, + "a.js should have been built" + ); - setTimeout(() => { helper.runAgain((stats, files, iteration) => { - // Not built when cached the second run stats.modules[0].name.should.containEql("c.js"); //stats.modules[0].built.should.be.exactly(false, "c.js should not have built"); @@ -226,67 +308,28 @@ describe("Compiler (caching)", function() { stats.modules[1].name.should.containEql("a.js"); //stats.modules[1].built.should.be.exactly(false, "a.js should not have built"); - const aContent = fs.readFileSync(tempFixture.aFilepath).toString().replace("This is a", "This is a MODIFIED"); + const aContent = fs + .readFileSync(tempFixture.aFilepath) + .toString() + .replace("This is a", "This is a MODIFIED"); - setTimeout(() => { - fs.writeFileSync(tempFixture.aFilepath, aContent); + fs.writeFileSync(tempFixture.aFilepath, aContent); - helper.runAgain((stats, files, iteration) => { + helper.runAgain((stats, files, iteration) => { + // And only a.js built after it was modified + stats.modules[0].name.should.containEql("c.js"); + //stats.modules[0].built.should.be.exactly(false, "c.js should not have built"); - // And only a.js built after it was modified - stats.modules[0].name.should.containEql("c.js"); - stats.modules[0].built.should.be.exactly(false, "c.js should not have built"); + stats.modules[1].name.should.containEql("a.js"); + stats.modules[1].built.should.be.exactly( + true, + "a.js should have been built" + ); - stats.modules[1].name.should.containEql("a.js"); - stats.modules[1].built.should.be.exactly(true, "a.js should have been built"); - - done(); - }); - }, 2100); + done(); + }); }); - }, 4100); - }); - }); - - it("should build when modified (even with no timeout)", (done) => { - - const options = {}; - const tempFixture = createTempFixture(); - - const helper = compile("./temp-cache-fixture/c", options, (stats, files) => { - - // Built the first time - stats.modules[0].name.should.containEql("c.js"); - stats.modules[0].built.should.be.exactly(true, "c.js should have been built"); - - stats.modules[1].name.should.containEql("a.js"); - stats.modules[1].built.should.be.exactly(true, "a.js should have been built"); - - helper.runAgain((stats, files, iteration) => { - - // Not built when cached the second run - stats.modules[0].name.should.containEql("c.js"); - //stats.modules[0].built.should.be.exactly(false, "c.js should not have built"); - - stats.modules[1].name.should.containEql("a.js"); - //stats.modules[1].built.should.be.exactly(false, "a.js should not have built"); - - const aContent = fs.readFileSync(tempFixture.aFilepath).toString().replace("This is a", "This is a MODIFIED"); - - fs.writeFileSync(tempFixture.aFilepath, aContent); - - helper.runAgain((stats, files, iteration) => { - - // And only a.js built after it was modified - stats.modules[0].name.should.containEql("c.js"); - //stats.modules[0].built.should.be.exactly(false, "c.js should not have built"); - - stats.modules[1].name.should.containEql("a.js"); - stats.modules[1].built.should.be.exactly(true, "a.js should have been built"); - - done(); - }); - }); - }); + } + ); }); }); diff --git a/test/Compiler.test.js b/test/Compiler.test.js index ab02e2650..c1eba8d13 100644 --- a/test/Compiler.test.js +++ b/test/Compiler.test.js @@ -12,18 +12,18 @@ const MemoryFs = require("memory-fs"); describe("Compiler", () => { function compile(entry, options, callback) { const noOutputPath = !options.output || !options.output.path; - if(!options.mode) options.mode = "production"; + if (!options.mode) options.mode = "production"; options = new WebpackOptionsDefaulter().process(options); options.entry = entry; options.context = path.join(__dirname, "fixtures"); - if(noOutputPath) options.output.path = "/"; + if (noOutputPath) options.output.path = "/"; options.output.pathinfo = true; options.optimization = { minimize: false }; const logs = { mkdirp: [], - writeFile: [], + writeFile: [] }; const c = webpack(options); @@ -42,9 +42,12 @@ describe("Compiler", () => { callback(); } }; - c.hooks.compilation.tap("CompilerTest", (compilation) => compilation.bail = true); + c.hooks.compilation.tap( + "CompilerTest", + compilation => (compilation.bail = true) + ); c.run((err, stats) => { - if(err) throw err; + if (err) throw err; should.strictEqual(typeof stats, "object"); const compilation = stats.compilation; stats = stats.toJson({ @@ -54,7 +57,7 @@ describe("Compiler", () => { should.strictEqual(typeof stats, "object"); stats.should.have.property("errors"); Array.isArray(stats.errors).should.be.ok(); - if(stats.errors.length > 0) { + if (stats.errors.length > 0) { stats.errors[0].should.be.instanceOf(Error); throw stats.errors[0]; } @@ -63,22 +66,23 @@ describe("Compiler", () => { }); } - it("should compile a single file to deep output", (done) => { - compile("./c", { - output: { - path: "/what", - filename: "the/hell.js", + it("should compile a single file to deep output", done => { + compile( + "./c", + { + output: { + path: "/what", + filename: "the/hell.js" + } + }, + (stats, files) => { + stats.logs.mkdirp.should.eql(["/what", "/what/the"]); + done(); } - }, (stats, files) => { - stats.logs.mkdirp.should.eql([ - "/what", - "/what/the", - ]); - done(); - }); + ); }); - it("should compile a single file", (done) => { + it("should compile a single file", done => { compile("./c", {}, (stats, files) => { files.should.have.property("/main.js").have.type("string"); Object.keys(files).should.be.eql(["/main.js"]); @@ -97,7 +101,7 @@ describe("Compiler", () => { }); }); - it("should compile a complex file", (done) => { + it("should compile a complex file", done => { compile("./main1", {}, (stats, files) => { files.should.have.property("/main.js").have.type("string"); Object.keys(files).should.be.eql(["/main.js"]); @@ -119,7 +123,7 @@ describe("Compiler", () => { }); }); - it("should compile a file with transitive dependencies", (done) => { + it("should compile a file with transitive dependencies", done => { compile("./abc", {}, (stats, files) => { files.should.have.property("/main.js").have.type("string"); Object.keys(files).should.be.eql(["/main.js"]); @@ -143,7 +147,7 @@ describe("Compiler", () => { }); }); - it("should compile a file with multiple chunks", (done) => { + it("should compile a file with multiple chunks", done => { compile("./chunks", {}, (stats, files) => { stats.chunks.length.should.be.eql(2); files.should.have.property("/main.js").have.type("string"); @@ -165,7 +169,7 @@ describe("Compiler", () => { bundle.should.not.containEql("fixtures"); chunk.should.not.containEql("fixtures"); bundle.should.containEql("webpackJsonp"); - chunk.should.containEql("window[\"webpackJsonp\"] || []).push"); + chunk.should.containEql('window["webpackJsonp"] || []).push'); done(); }); }); @@ -177,21 +181,21 @@ describe("Compiler", () => { context: path.join(__dirname, "fixtures"), output: { path: "/", - pathinfo: true, + pathinfo: true } }); }); describe("purgeInputFileSystem", () => { - it("invokes purge() if inputFileSystem.purge", (done) => { + it("invokes purge() if inputFileSystem.purge", done => { const mockPurge = sinon.spy(); compiler.inputFileSystem = { - purge: mockPurge, + purge: mockPurge }; compiler.purgeInputFileSystem(); mockPurge.callCount.should.be.exactly(1); done(); }); - it("does NOT invoke purge() if !inputFileSystem.purge", (done) => { + it("does NOT invoke purge() if !inputFileSystem.purge", done => { const mockPurge = sinon.spy(); compiler.inputFileSystem = null; compiler.purgeInputFileSystem(); @@ -200,7 +204,7 @@ describe("Compiler", () => { }); }); describe("isChild", () => { - it("returns booleanized this.parentCompilation", (done) => { + it("returns booleanized this.parentCompilation", done => { compiler.parentCompilation = "stringyStringString"; const response1 = compiler.isChild(); response1.should.be.exactly(true); @@ -254,8 +258,8 @@ describe("Compiler", () => { }); compiler.outputFileSystem = new MemoryFs(); compiler.run((err, stats) => { - if(err) return done(err); - if(compiler.outputFileSystem.existsSync("/bundle.js")) + if (err) return done(err); + if (compiler.outputFileSystem.existsSync("/bundle.js")) return done(new Error("Bundle should not be created on error")); done(); }); @@ -273,8 +277,8 @@ describe("Compiler", () => { compiler.outputFileSystem = new MemoryFs(); const watching = compiler.watch({}, (err, stats) => { watching.close(); - if(err) return done(err); - if(compiler.outputFileSystem.existsSync("/bundle.js")) + if (err) return done(err); + if (compiler.outputFileSystem.existsSync("/bundle.js")) return done(new Error("Bundle should not be created on error")); done(); }); diff --git a/test/ConfigTestCases.test.js b/test/ConfigTestCases.test.js index 2edcd72b6..8677f8fb9 100644 --- a/test/ConfigTestCases.test.js +++ b/test/ConfigTestCases.test.js @@ -17,46 +17,65 @@ describe("ConfigTestCases", () => { const casesPath = path.join(__dirname, "configCases"); let categories = fs.readdirSync(casesPath); - categories = categories.map((cat) => { + categories = categories.map(cat => { return { name: cat, - tests: fs.readdirSync(path.join(casesPath, cat)).filter((folder) => { - return folder.indexOf("_") < 0; - }).sort().filter((testName) => { - const testDirectory = path.join(casesPath, cat, testName); - const filterPath = path.join(testDirectory, "test.filter.js"); - if(fs.existsSync(filterPath) && !require(filterPath)()) { - describe.skip(testName, () => it("filtered")); - return false; - } - return true; - }) + tests: fs + .readdirSync(path.join(casesPath, cat)) + .filter(folder => { + return folder.indexOf("_") < 0; + }) + .sort() + .filter(testName => { + const testDirectory = path.join(casesPath, cat, testName); + const filterPath = path.join(testDirectory, "test.filter.js"); + if (fs.existsSync(filterPath) && !require(filterPath)()) { + describe.skip(testName, () => it("filtered")); + return false; + } + return true; + }) }; }); - categories.forEach((category) => { + categories.forEach(category => { describe(category.name, () => { - category.tests.forEach((testName) => { + category.tests.forEach(testName => { const suite = describe(testName, () => {}); it(testName + " should compile", function(done) { const testDirectory = path.join(casesPath, category.name, testName); - const outputDirectory = path.join(__dirname, "js", "config", category.name, testName); - const options = prepareOptions(require(path.join(testDirectory, "webpack.config.js"))); + const outputDirectory = path.join( + __dirname, + "js", + "config", + category.name, + testName + ); + const options = prepareOptions( + require(path.join(testDirectory, "webpack.config.js")) + ); const optionsArr = [].concat(options); optionsArr.forEach((options, idx) => { - if(!options.context) options.context = testDirectory; - if(!options.mode) options.mode = "production"; - if(!options.optimization) options.optimization = {}; - if(options.optimization.minimize === undefined) options.optimization.minimize = false; - if(!options.entry) options.entry = "./index.js"; - if(!options.target) options.target = "async-node"; - if(!options.output) options.output = {}; - if(!options.output.path) options.output.path = outputDirectory; - if(typeof options.output.pathinfo === "undefined") options.output.pathinfo = true; - if(!options.output.filename) options.output.filename = "bundle" + idx + ".js"; + if (!options.context) options.context = testDirectory; + if (!options.mode) options.mode = "production"; + if (!options.optimization) options.optimization = {}; + if (options.optimization.minimize === undefined) + options.optimization.minimize = false; + if (!options.entry) options.entry = "./index.js"; + if (!options.target) options.target = "async-node"; + if (!options.output) options.output = {}; + if (!options.output.path) options.output.path = outputDirectory; + if (typeof options.output.pathinfo === "undefined") + options.output.pathinfo = true; + if (!options.output.filename) + options.output.filename = "bundle" + idx + ".js"; }); let testConfig = { findBundle: function(i, options) { - if(fs.existsSync(path.join(options.output.path, "bundle" + i + ".js"))) { + if ( + fs.existsSync( + path.join(options.output.path, "bundle" + i + ".js") + ) + ) { return "./bundle" + i + ".js"; } }, @@ -64,29 +83,63 @@ describe("ConfigTestCases", () => { }; try { // try to load a test file - testConfig = Object.assign(testConfig, require(path.join(testDirectory, "test.config.js"))); - } catch(e) {} + testConfig = Object.assign( + testConfig, + require(path.join(testDirectory, "test.config.js")) + ); + } catch (e) {} this.timeout(testConfig.timeout); webpack(options, (err, stats) => { - if(err) { + if (err) { const fakeStats = { errors: [err.stack] }; - if(checkArrayExpectation(testDirectory, fakeStats, "error", "Error", done)) return; + if ( + checkArrayExpectation( + testDirectory, + fakeStats, + "error", + "Error", + done + ) + ) + return; // Wait for uncatched errors to occur return setTimeout(done, 200); } const statOptions = Stats.presetToOptions("verbose"); statOptions.colors = false; mkdirp.sync(outputDirectory); - fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8"); + fs.writeFileSync( + path.join(outputDirectory, "stats.txt"), + stats.toString(statOptions), + "utf-8" + ); const jsonStats = stats.toJson({ errorDetails: true }); - if(checkArrayExpectation(testDirectory, jsonStats, "error", "Error", done)) return; - if(checkArrayExpectation(testDirectory, jsonStats, "warning", "Warning", done)) return; + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "error", + "Error", + done + ) + ) + return; + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "warning", + "Warning", + done + ) + ) + return; let exportedTests = 0; function _it(title, fn) { @@ -101,47 +154,78 @@ describe("ConfigTestCases", () => { }; function _require(currentDirectory, module) { - if(Array.isArray(module) || /^\.\.?\//.test(module)) { + if (Array.isArray(module) || /^\.\.?\//.test(module)) { let fn; let content; let p; - if(Array.isArray(module)) { + if (Array.isArray(module)) { p = path.join(currentDirectory, module[0]); - content = module.map((arg) => { - p = path.join(currentDirectory, arg); - return fs.readFileSync(p, "utf-8"); - }).join("\n"); + content = module + .map(arg => { + p = path.join(currentDirectory, arg); + return fs.readFileSync(p, "utf-8"); + }) + .join("\n"); } else { p = path.join(currentDirectory, module); content = fs.readFileSync(p, "utf-8"); } - if(options.target === "web" || options.target === "webworker") { - fn = vm.runInNewContext("(function(require, module, exports, __dirname, __filename, it, window) {" + content + "\n})", globalContext, p); + if ( + options.target === "web" || + options.target === "webworker" + ) { + fn = vm.runInNewContext( + "(function(require, module, exports, __dirname, __filename, it, window) {" + + content + + "\n})", + globalContext, + p + ); } else { - fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it) {" + content + "\n})", p); + fn = vm.runInThisContext( + "(function(require, module, exports, __dirname, __filename, it) {" + + content + + "\n})", + p + ); } const m = { exports: {} }; - fn.call(m.exports, _require.bind(null, path.dirname(p)), m, m.exports, path.dirname(p), p, _it, globalContext); + fn.call( + m.exports, + _require.bind(null, path.dirname(p)), + m, + m.exports, + path.dirname(p), + p, + _it, + globalContext + ); return m.exports; - } else if(testConfig.modules && module in testConfig.modules) { + } else if (testConfig.modules && module in testConfig.modules) { return testConfig.modules[module]; } else return require(module); } let filesCount = 0; - if(testConfig.noTests) return process.nextTick(done); - for(let i = 0; i < optionsArr.length; i++) { + if (testConfig.noTests) return process.nextTick(done); + for (let i = 0; i < optionsArr.length; i++) { const bundlePath = testConfig.findBundle(i, optionsArr[i]); - if(bundlePath) { + if (bundlePath) { filesCount++; _require(outputDirectory, bundlePath); } } // give a free pass to compilation that generated an error - if(!jsonStats.errors.length && filesCount !== optionsArr.length) return done(new Error("Should have found at least one bundle file per webpack config")); - if(exportedTests < filesCount) return done(new Error("No tests exported by test case")); + if (!jsonStats.errors.length && filesCount !== optionsArr.length) + return done( + new Error( + "Should have found at least one bundle file per webpack config" + ) + ); + if (exportedTests < filesCount) + return done(new Error("No tests exported by test case")); process.nextTick(done); }); }); diff --git a/test/ContextModuleFactory.unittest.js b/test/ContextModuleFactory.unittest.js index 6df1f20dd..17b058b2f 100644 --- a/test/ContextModuleFactory.unittest.js +++ b/test/ContextModuleFactory.unittest.js @@ -20,16 +20,20 @@ describe("ContextModuleFactory", function() { err.code = "ENOENT"; setTimeout(() => callback(err, null)); }; - factory.resolveDependencies(memfs, { - resource: "/", - recursive: true, - regExp: /.*/ - }, (err, res) => { - (!!err).should.be.false(); - res.should.be.an.Array(); - res.length.should.be.exactly(0); - done(); - }); + factory.resolveDependencies( + memfs, + { + resource: "/", + recursive: true, + regExp: /.*/ + }, + (err, res) => { + (!!err).should.be.false(); + res.should.be.an.Array(); + res.length.should.be.exactly(0); + done(); + } + ); }); it("should report an error when non-ENOENT errors happen", function(done) { memfs.readdir = (dir, callback) => { @@ -40,15 +44,19 @@ describe("ContextModuleFactory", function() { err.code = "EACCES"; setTimeout(() => callback(err, null)); }; - factory.resolveDependencies(memfs, { - resource: "/", - recursive: true, - regExp: /.*/ - }, (err, res) => { - err.should.be.an.Error(); - (!!res).should.be.false(); - done(); - }); + factory.resolveDependencies( + memfs, + { + resource: "/", + recursive: true, + regExp: /.*/ + }, + (err, res) => { + err.should.be.an.Error(); + (!!res).should.be.false(); + done(); + } + ); }); }); }); diff --git a/test/DelegatedModule.unittest.js b/test/DelegatedModule.unittest.js index 6b6930a4c..fdfc9934c 100644 --- a/test/DelegatedModule.unittest.js +++ b/test/DelegatedModule.unittest.js @@ -16,11 +16,16 @@ describe("DelegatedModule", function() { beforeEach(function() { hashedText = ""; hash = { - update: (text) => { + update: text => { hashedText += text; } }; - const delegatedModule = new DelegatedModule(sourceRequest, data, type, userRequest); + const delegatedModule = new DelegatedModule( + sourceRequest, + data, + type, + userRequest + ); delegatedModule.updateHash(hash); }); it("updates hash with delegated module ID", function() { diff --git a/test/DependenciesBlockVariable.unittest.js b/test/DependenciesBlockVariable.unittest.js index 43d19cd1e..5e8dcb1c9 100644 --- a/test/DependenciesBlockVariable.unittest.js +++ b/test/DependenciesBlockVariable.unittest.js @@ -5,9 +5,7 @@ const sinon = require("sinon"); const DependenciesBlockVariable = require("../lib/DependenciesBlockVariable"); describe("DependenciesBlockVariable", () => { - let DependenciesBlockVariableInstance, - dependencyMock, - sandbox; + let DependenciesBlockVariableInstance, dependencyMock, sandbox; before(() => { sandbox = sinon.sandbox.create(); @@ -20,7 +18,9 @@ describe("DependenciesBlockVariable", () => { }; DependenciesBlockVariableInstance = new DependenciesBlockVariable( "dependencies-name", - "expression", [dependencyMock]); + "expression", + [dependencyMock] + ); }); afterEach(() => sandbox.restore()); @@ -55,10 +55,9 @@ describe("DependenciesBlockVariable", () => { }); describe("expressionSource", () => { - let dependencyTemplates, - applyMock; + let dependencyTemplates, applyMock; - before(() => applyMock = sandbox.spy()); + before(() => (applyMock = sandbox.spy())); it("aplies information inside dependency templates", () => { dependencyTemplates = { @@ -69,7 +68,9 @@ describe("DependenciesBlockVariable", () => { } }; DependenciesBlockVariableInstance.expressionSource( - dependencyTemplates, {}, {} + dependencyTemplates, + {}, + {} ); should(applyMock.calledOnce).be.true(); }); @@ -82,7 +83,9 @@ describe("DependenciesBlockVariable", () => { }; should(() => { DependenciesBlockVariableInstance.expressionSource( - dependencyTemplates, {}, {} + dependencyTemplates, + {}, + {} ); }).throw("No template for dependency: DependencyMock"); }); diff --git a/test/Errors.test.js b/test/Errors.test.js index 10043f734..5f08dfd5d 100644 --- a/test/Errors.test.js +++ b/test/Errors.test.js @@ -29,7 +29,7 @@ describe("Errors", () => { const c = webpack(options); customOutputFilesystem(c); c.run((err, stats) => { - if(err) throw err; + if (err) throw err; should.strictEqual(typeof stats, "object"); stats = stats.toJson({ errorDetails: false @@ -42,130 +42,149 @@ describe("Errors", () => { callback(stats.errors, stats.warnings); }); } - it("should throw an error if file doesn't exist", (done) => { - getErrors({ - mode: "development", - entry: "./missingFile" - }, (errors, warnings) => { - errors.length.should.be.eql(2); - warnings.length.should.be.eql(0); - errors.sort(); - let lines = errors[0].split("\n"); - lines[0].should.match(/missingFile.js/); - lines[1].should.match(/^Module not found/); - lines[1].should.match(/\.\/dir\/missing2/); - lines[2].should.match(/missingFile.js 12:9/); - lines = errors[1].split("\n"); - lines[0].should.match(/missingFile.js/); - lines[1].should.match(/^Module not found/); - lines[1].should.match(/\.\/missing/); - lines[2].should.match(/missingFile.js 4:0/); - done(); - }); + it("should throw an error if file doesn't exist", done => { + getErrors( + { + mode: "development", + entry: "./missingFile" + }, + (errors, warnings) => { + errors.length.should.be.eql(2); + warnings.length.should.be.eql(0); + errors.sort(); + let lines = errors[0].split("\n"); + lines[0].should.match(/missingFile.js/); + lines[1].should.match(/^Module not found/); + lines[1].should.match(/\.\/dir\/missing2/); + lines[2].should.match(/missingFile.js 12:9/); + lines = errors[1].split("\n"); + lines[0].should.match(/missingFile.js/); + lines[1].should.match(/^Module not found/); + lines[1].should.match(/\.\/missing/); + lines[2].should.match(/missingFile.js 4:0/); + done(); + } + ); }); - it("should report require.extensions as unsupported", (done) => { - getErrors({ - mode: "development", - entry: "./require.extensions" - }, (errors, warnings) => { - errors.length.should.be.eql(0); - warnings.length.should.be.eql(1); - const lines = warnings[0].split("\n"); - lines[0].should.match(/require.extensions\.js/); - lines[1].should.match(/require.extensions is not supported by webpack/); - done(); - }); - }); - it("should warn about case-sensitive module names", (done) => { - getErrors({ - mode: "development", - entry: "./case-sensitive" - }, (errors, warnings) => { - if(errors.length === 0) { + it("should report require.extensions as unsupported", done => { + getErrors( + { + mode: "development", + entry: "./require.extensions" + }, + (errors, warnings) => { + errors.length.should.be.eql(0); warnings.length.should.be.eql(1); const lines = warnings[0].split("\n"); - lines[4].should.match(/FILE\.js/); - lines[5].should.match(/Used by/); - lines[6].should.match(/case-sensitive/); - lines[7].should.match(/file\.js/); - lines[8].should.match(/Used by/); - lines[9].should.match(/case-sensitive/); - } else { - errors.length.should.be.eql(1); - warnings.length.should.be.eql(0); + lines[0].should.match(/require.extensions\.js/); + lines[1].should.match(/require.extensions is not supported by webpack/); + done(); } - done(); - }); + ); }); - it("should warn when not using mode", (done) => { - getErrors({ - entry: "./entry-point", - }, (errors, warnings) => { - errors.length.should.be.eql(0); - warnings.length.should.be.eql(1); - let lines = warnings[0].split("\n"); - lines[0].should.match(/configuration/); - lines[1].should.match(/mode/); - lines[1].should.match(/development/); - lines[1].should.match(/production/); - done(); - }); - }); - it("should not warn if the NoEmitOnErrorsPlugin is used over the NoErrorsPlugin", (done) => { - getErrors({ - mode: "production", - entry: "./no-errors-deprecate" - }, (errors, warnings) => { - errors.length.should.be.eql(0); - warnings.length.should.be.eql(0); - done(); - }); - }); - it("should not not emit if NoEmitOnErrorsPlugin is used and there is an error", (done) => { - getErrors({ - mode: "production", - entry: "./missingFile" - }, (errors, warnings) => { - errors.length.should.be.eql(2); - warnings.length.should.be.eql(0); - errors.sort(); - let lines = errors[0].split("\n"); - lines[0].should.match(/missingFile.js/); - lines[1].should.match(/^Module not found/); - lines[1].should.match(/\.\/dir\/missing2/); - lines[2].should.match(/missingFile.js 12:9/); - lines = errors[1].split("\n"); - lines[0].should.match(/missingFile.js/); - lines[1].should.match(/^Module not found/); - lines[1].should.match(/\.\/missing/); - lines[2].should.match(/missingFile.js 4:0/); - done(); - }); - }); - it("should throw an error when trying to use [chunkhash] when it's invalid", (done) => { - getErrors({ - mode: "development", - entry: { - a: "./entry-point", - b: "./entry-point", - c: "./entry-point" + it("should warn about case-sensitive module names", done => { + getErrors( + { + mode: "development", + entry: "./case-sensitive" }, - output: { - filename: "[chunkhash].js" + (errors, warnings) => { + if (errors.length === 0) { + warnings.length.should.be.eql(1); + const lines = warnings[0].split("\n"); + lines[4].should.match(/FILE\.js/); + lines[5].should.match(/Used by/); + lines[6].should.match(/case-sensitive/); + lines[7].should.match(/file\.js/); + lines[8].should.match(/Used by/); + lines[9].should.match(/case-sensitive/); + } else { + errors.length.should.be.eql(1); + warnings.length.should.be.eql(0); + } + done(); + } + ); + }); + it("should warn when not using mode", done => { + getErrors( + { + entry: "./entry-point" }, - plugins: [ - new webpack.HotModuleReplacementPlugin() - ] - }, (errors, warnings) => { - errors.length.should.be.eql(3); - warnings.length.should.be.eql(0); - errors.forEach((error) => { - const lines = error.split("\n"); - lines[0].should.match(/chunk (a|b|c)/); - lines[2].should.match(/\[chunkhash\].js/); - lines[2].should.match(/use \[hash\] instead/); - }); - done(); - }); + (errors, warnings) => { + errors.length.should.be.eql(0); + warnings.length.should.be.eql(1); + let lines = warnings[0].split("\n"); + lines[0].should.match(/configuration/); + lines[1].should.match(/mode/); + lines[1].should.match(/development/); + lines[1].should.match(/production/); + done(); + } + ); + }); + it("should not warn if the NoEmitOnErrorsPlugin is used over the NoErrorsPlugin", done => { + getErrors( + { + mode: "production", + entry: "./no-errors-deprecate" + }, + (errors, warnings) => { + errors.length.should.be.eql(0); + warnings.length.should.be.eql(0); + done(); + } + ); + }); + it("should not not emit if NoEmitOnErrorsPlugin is used and there is an error", done => { + getErrors( + { + mode: "production", + entry: "./missingFile" + }, + (errors, warnings) => { + errors.length.should.be.eql(2); + warnings.length.should.be.eql(0); + errors.sort(); + let lines = errors[0].split("\n"); + lines[0].should.match(/missingFile.js/); + lines[1].should.match(/^Module not found/); + lines[1].should.match(/\.\/dir\/missing2/); + lines[2].should.match(/missingFile.js 12:9/); + lines = errors[1].split("\n"); + lines[0].should.match(/missingFile.js/); + lines[1].should.match(/^Module not found/); + lines[1].should.match(/\.\/missing/); + lines[2].should.match(/missingFile.js 4:0/); + done(); + } + ); + }); + it("should throw an error when trying to use [chunkhash] when it's invalid", done => { + getErrors( + { + mode: "development", + entry: { + a: "./entry-point", + b: "./entry-point", + c: "./entry-point" + }, + output: { + filename: "[chunkhash].js" + }, + plugins: [new webpack.HotModuleReplacementPlugin()] + }, + (errors, warnings) => { + errors.length.should.be.eql(3); + warnings.length.should.be.eql(0); + errors.forEach(error => { + const lines = error.split("\n"); + lines[0].should.match(/chunk (a|b|c)/); + lines[2].should.match(/\[chunkhash\].js/); + lines[2].should.match(/use \[hash\] instead/); + }); + done(); + } + ); }); }); diff --git a/test/Examples.test.js b/test/Examples.test.js index 7544a971b..f57016c5d 100644 --- a/test/Examples.test.js +++ b/test/Examples.test.js @@ -10,23 +10,25 @@ describe("Examples", () => { const basePath = path.join(__dirname, "..", "examples"); const examples = require("../examples/examples.js"); - examples.forEach((examplePath) => { + examples.forEach(examplePath => { const filterPath = path.join(examplePath, "test.filter.js"); - if(fs.existsSync(filterPath) && !require(filterPath)()) { + if (fs.existsSync(filterPath) && !require(filterPath)()) { describe.skip(path.relative(basePath, examplePath), () => it("filtered")); return; } - it("should compile " + path.relative(basePath, examplePath), function(done) { + it("should compile " + path.relative(basePath, examplePath), function( + done + ) { this.timeout(20000); let options = {}; let webpackConfigPath = path.join(examplePath, "webpack.config.js"); - webpackConfigPath = webpackConfigPath.substr(0, 1).toUpperCase() + webpackConfigPath.substr(1); - if(fs.existsSync(webpackConfigPath)) + webpackConfigPath = + webpackConfigPath.substr(0, 1).toUpperCase() + + webpackConfigPath.substr(1); + if (fs.existsSync(webpackConfigPath)) options = require(webpackConfigPath); - if(Array.isArray(options)) - options.forEach(processOptions); - else - processOptions(options); + if (Array.isArray(options)) options.forEach(processOptions); + else processOptions(options); function processOptions(options) { options.context = examplePath; @@ -34,22 +36,22 @@ describe("Examples", () => { options.output.pathinfo = true; options.output.path = path.join(examplePath, "dist"); options.output.publicPath = "dist/"; - if(!options.entry) - options.entry = "./example.js"; - if(!options.plugins) - options.plugins = []; + if (!options.entry) options.entry = "./example.js"; + if (!options.plugins) options.plugins = []; // To support deprecated loaders // TODO remove in webpack 5 - options.plugins.push(new webpack.LoaderOptionsPlugin({ - options: {} - })); + options.plugins.push( + new webpack.LoaderOptionsPlugin({ + options: {} + }) + ); } webpack(options, (err, stats) => { - if(err) return done(err); + if (err) return done(err); stats = stats.toJson({ errorDetails: true }); - if(stats.errors.length > 0) { + if (stats.errors.length > 0) { return done(new Error(stats.errors[0])); } done(); diff --git a/test/ExternalModule.unittest.js b/test/ExternalModule.unittest.js index 6b86152b6..abafa5ed6 100644 --- a/test/ExternalModule.unittest.js +++ b/test/ExternalModule.unittest.js @@ -13,11 +13,7 @@ describe("ExternalModule", function() { beforeEach(function() { request = "some/request"; type = "some-type"; - externalModule = new ExternalModule( - request, - type, - `${type} ${request}` - ); + externalModule = new ExternalModule(request, type, `${type} ${request}`); }); describe("#identifier", function() { it("returns an identifier for this module", function() { @@ -103,10 +99,14 @@ describe("ExternalModule", function() { // set up const type = "window"; const varName = ["foo", "bar"]; - const expected = "(function() { module.exports = window[\"foo\"][\"bar\"]; }());"; + const expected = + '(function() { module.exports = window["foo"]["bar"]; }());'; // invoke - const result = externalModule.getSourceForGlobalVariableExternal(varName, type); + const result = externalModule.getSourceForGlobalVariableExternal( + varName, + type + ); // check result.should.eql(expected); @@ -117,10 +117,13 @@ describe("ExternalModule", function() { // set up const type = "window"; const varName = "foo"; - const expected = "(function() { module.exports = window[\"foo\"]; }());"; + const expected = '(function() { module.exports = window["foo"]; }());'; // invoke - const result = externalModule.getSourceForGlobalVariableExternal(varName, type); + const result = externalModule.getSourceForGlobalVariableExternal( + varName, + type + ); // check result.should.eql(expected); @@ -133,10 +136,13 @@ describe("ExternalModule", function() { it("use the first to require a module and the rest as lookup on the required module", function() { // set up const varName = ["module", "look", "up"]; - const expected = "module.exports = require(module)[\"look\"][\"up\"];"; + const expected = 'module.exports = require(module)["look"]["up"];'; // invoke - const result = externalModule.getSourceForCommonJsExternal(varName, type); + const result = externalModule.getSourceForCommonJsExternal( + varName, + type + ); // check result.should.eql(expected); @@ -147,10 +153,13 @@ describe("ExternalModule", function() { // set up const type = "window"; const varName = "foo"; - const expected = "module.exports = require(\"foo\");"; + const expected = 'module.exports = require("foo");'; // invoke - const result = externalModule.getSourceForCommonJsExternal(varName, type); + const result = externalModule.getSourceForCommonJsExternal( + varName, + type + ); // check result.should.eql(expected); @@ -167,7 +176,10 @@ describe("ExternalModule", function() { `; // invoke - const result = externalModule.checkExternalVariable(variableToCheck, request); + const result = externalModule.checkExternalVariable( + variableToCheck, + request + ); // check result.should.eql(expected); @@ -182,7 +194,11 @@ describe("ExternalModule", function() { const expected = "module.exports = __WEBPACK_EXTERNAL_MODULE_someId__;"; // invoke - const result = externalModule.getSourceForAmdOrUmdExternal(id, optional, request); + const result = externalModule.getSourceForAmdOrUmdExternal( + id, + optional, + request + ); // check result.should.eql(expected); @@ -196,7 +212,11 @@ describe("ExternalModule", function() { module.exports = __WEBPACK_EXTERNAL_MODULE_someId__;`; // invoke - const result = externalModule.getSourceForAmdOrUmdExternal(id, optional, request); + const result = externalModule.getSourceForAmdOrUmdExternal( + id, + optional, + request + ); // check result.should.eql(expected); @@ -224,7 +244,10 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_someId__;`; module.exports = some/request;`; // invoke - const result = externalModule.getSourceForDefaultCase(optional, request); + const result = externalModule.getSourceForDefaultCase( + optional, + request + ); // check result.should.eql(expected); @@ -238,7 +261,7 @@ module.exports = some/request;`; beforeEach(function() { hashedText = ""; hash = { - update: (text) => { + update: text => { hashedText += text; } }; @@ -262,7 +285,7 @@ module.exports = some/request;`; beforeEach(function() { hashedText = ""; hash = { - update: (text) => { + update: text => { hashedText += text; } }; diff --git a/test/HarmonyExportImportedSpecifierDependency.unittest.js b/test/HarmonyExportImportedSpecifierDependency.unittest.js index e9d6e33c9..3f70bc93b 100644 --- a/test/HarmonyExportImportedSpecifierDependency.unittest.js +++ b/test/HarmonyExportImportedSpecifierDependency.unittest.js @@ -6,7 +6,8 @@ const HarmonyExportImportedSpecifierDependency = require("../lib/dependencies/Ha describe("HarmonyExportImportedSpecifierDependency", () => { describe("getHashValue", () => { - it("should return empty string on missing module", () => { // see e.g. PR #4368 + it("should return empty string on missing module", () => { + // see e.g. PR #4368 var instance = new HarmonyExportImportedSpecifierDependency(); should(instance.getHashValue(undefined)).be.eql(""); should(instance.getHashValue(null)).be.eql(""); diff --git a/test/HotModuleReplacementPlugin.test.js b/test/HotModuleReplacementPlugin.test.js index 6c2c0b574..519e10a15 100644 --- a/test/HotModuleReplacementPlugin.test.js +++ b/test/HotModuleReplacementPlugin.test.js @@ -8,17 +8,25 @@ const webpack = require("../"); describe("HotModuleReplacementPlugin", function() { this.timeout(10000); - it("should not have circular hashes but equal if unmodified", (done) => { + it("should not have circular hashes but equal if unmodified", done => { const entryFile = path.join(__dirname, "js", "entry.js"); - const statsFile1 = path.join(__dirname, "js", "HotModuleReplacementPlugin.test.stats1.txt"); - const statsFile2 = path.join(__dirname, "js", "HotModuleReplacementPlugin.test.stats2.txt"); + const statsFile1 = path.join( + __dirname, + "js", + "HotModuleReplacementPlugin.test.stats1.txt" + ); + const statsFile2 = path.join( + __dirname, + "js", + "HotModuleReplacementPlugin.test.stats2.txt" + ); const recordsFile = path.join(__dirname, "js", "records.json"); try { fs.mkdirSync(path.join(__dirname, "js")); - } catch(e) {} + } catch (e) {} try { fs.unlinkSync(recordsFile); - } catch(e) {} + } catch (e) {} const compiler = webpack({ cache: false, entry: entryFile, @@ -33,33 +41,42 @@ describe("HotModuleReplacementPlugin", function() { }); fs.writeFileSync(entryFile, "1", "utf-8"); compiler.run((err, stats) => { - if(err) throw err; + if (err) throw err; const oldHash1 = stats.toJson().hash; fs.writeFileSync(statsFile1, stats.toString()); compiler.run((err, stats) => { - if(err) throw err; + if (err) throw err; const lastHash1 = stats.toJson().hash; fs.writeFileSync(statsFile2, stats.toString()); - lastHash1.should.be.eql(oldHash1, "hash shouldn't change when bundle stay equal"); + lastHash1.should.be.eql( + oldHash1, + "hash shouldn't change when bundle stay equal" + ); fs.writeFileSync(entryFile, "2", "utf-8"); compiler.run((err, stats) => { - if(err) throw err; + if (err) throw err; const lastHash2 = stats.toJson().hash; fs.writeFileSync(statsFile1, stats.toString()); - lastHash2.should.not.be.eql(lastHash1, "hash should change when bundle changes"); + lastHash2.should.not.be.eql( + lastHash1, + "hash should change when bundle changes" + ); fs.writeFileSync(entryFile, "1", "utf-8"); compiler.run((err, stats) => { - if(err) throw err; + if (err) throw err; const currentHash1 = stats.toJson().hash; fs.writeFileSync(statsFile2, stats.toString()); - currentHash1.should.not.be.eql(lastHash1, "hash shouldn't change to the first hash if bundle changed back to first bundle"); + currentHash1.should.not.be.eql( + lastHash1, + "hash shouldn't change to the first hash if bundle changed back to first bundle" + ); fs.writeFileSync(entryFile, "2", "utf-8"); compiler.run((err, stats) => { - if(err) throw err; + if (err) throw err; const currentHash2 = stats.toJson().hash; fs.writeFileSync(statsFile1, stats.toString()); compiler.run((err, stats) => { - if(err) throw err; + if (err) throw err; stats.toJson().hash.should.be.eql(currentHash2); currentHash2.should.not.be.eql(lastHash2); currentHash1.should.not.be.eql(currentHash2); diff --git a/test/HotTestCases.test.js b/test/HotTestCases.test.js index df2a8d398..1f42a9605 100644 --- a/test/HotTestCases.test.js +++ b/test/HotTestCases.test.js @@ -11,63 +11,89 @@ const webpack = require("../lib/webpack"); describe("HotTestCases", () => { const casesPath = path.join(__dirname, "hotCases"); - let categories = fs.readdirSync(casesPath).filter((dir) => - fs.statSync(path.join(casesPath, dir)).isDirectory()); - categories = categories.map((cat) => { + let categories = fs + .readdirSync(casesPath) + .filter(dir => fs.statSync(path.join(casesPath, dir)).isDirectory()); + categories = categories.map(cat => { return { name: cat, - tests: fs.readdirSync(path.join(casesPath, cat)).filter((folder) => folder.indexOf("_") < 0) + tests: fs + .readdirSync(path.join(casesPath, cat)) + .filter(folder => folder.indexOf("_") < 0) }; }); - categories.forEach((category) => { + categories.forEach(category => { describe(category.name, () => { - category.tests.forEach((testName) => { + category.tests.forEach(testName => { const suite = describe(testName, function() { this.timeout(10000); }); - it(testName + " should compile", (done) => { + it(testName + " should compile", done => { const testDirectory = path.join(casesPath, category.name, testName); - const outputDirectory = path.join(__dirname, "js", "hot-cases", category.name, testName); + const outputDirectory = path.join( + __dirname, + "js", + "hot-cases", + category.name, + testName + ); const recordsPath = path.join(outputDirectory, "records.json"); - if(fs.existsSync(recordsPath)) - fs.unlinkSync(recordsPath); + if (fs.existsSync(recordsPath)) fs.unlinkSync(recordsPath); const fakeUpdateLoaderOptions = { updateIndex: 0 }; const configPath = path.join(testDirectory, "webpack.config.js"); let options = {}; - if(fs.existsSync(configPath)) - options = require(configPath); - if(!options.mode) options.mode = "development"; - if(!options.context) options.context = testDirectory; - if(!options.entry) options.entry = "./index.js"; - if(!options.output) options.output = {}; - if(!options.output.path) options.output.path = outputDirectory; - if(!options.output.filename) options.output.filename = "bundle.js"; - if(options.output.pathinfo === undefined) options.output.pathinfo = true; - if(!options.module) options.module = {}; - if(!options.module.rules) options.module.rules = []; + if (fs.existsSync(configPath)) options = require(configPath); + if (!options.mode) options.mode = "development"; + if (!options.context) options.context = testDirectory; + if (!options.entry) options.entry = "./index.js"; + if (!options.output) options.output = {}; + if (!options.output.path) options.output.path = outputDirectory; + if (!options.output.filename) options.output.filename = "bundle.js"; + if (options.output.pathinfo === undefined) + options.output.pathinfo = true; + if (!options.module) options.module = {}; + if (!options.module.rules) options.module.rules = []; options.module.rules.push({ test: /\.js$/, loader: path.join(__dirname, "hotCases", "fake-update-loader.js"), enforce: "pre" }); - if(!options.target) options.target = "async-node"; - if(!options.plugins) options.plugins = []; + if (!options.target) options.target = "async-node"; + if (!options.plugins) options.plugins = []; options.plugins.push( new webpack.HotModuleReplacementPlugin(), new webpack.NamedModulesPlugin(), new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions) ); - if(!options.recordsPath) options.recordsPath = recordsPath; + if (!options.recordsPath) options.recordsPath = recordsPath; const compiler = webpack(options); compiler.run((err, stats) => { - if(err) return done(err); + if (err) return done(err); const jsonStats = stats.toJson({ errorDetails: true }); - if(checkArrayExpectation(testDirectory, jsonStats, "error", "Error", done)) return; - if(checkArrayExpectation(testDirectory, jsonStats, "warning", "Warning", done)) return; + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "error", + "Error", + done + ) + ) + return; + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "warning", + "Warning", + done + ) + ) + return; let exportedTests = 0; function _it(title, fn) { @@ -81,29 +107,65 @@ describe("HotTestCases", () => { function _next(callback) { fakeUpdateLoaderOptions.updateIndex++; compiler.run((err, stats) => { - if(err) return done(err); + if (err) return done(err); const jsonStats = stats.toJson({ errorDetails: true }); - if(checkArrayExpectation(testDirectory, jsonStats, "error", "errors" + fakeUpdateLoaderOptions.updateIndex, "Error", done)) return; - if(checkArrayExpectation(testDirectory, jsonStats, "warning", "warnings" + fakeUpdateLoaderOptions.updateIndex, "Warning", done)) return; - if(callback) callback(jsonStats); + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "error", + "errors" + fakeUpdateLoaderOptions.updateIndex, + "Error", + done + ) + ) + return; + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "warning", + "warnings" + fakeUpdateLoaderOptions.updateIndex, + "Warning", + done + ) + ) + return; + if (callback) callback(jsonStats); }); } function _require(module) { - if(module.substr(0, 2) === "./") { + if (module.substr(0, 2) === "./") { const p = path.join(outputDirectory, module); - const fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, NEXT, STATS) {" + fs.readFileSync(p, "utf-8") + "\n})", p); + const fn = vm.runInThisContext( + "(function(require, module, exports, __dirname, __filename, it, NEXT, STATS) {" + + fs.readFileSync(p, "utf-8") + + "\n})", + p + ); const m = { exports: {} }; - fn.call(m.exports, _require, m, m.exports, outputDirectory, p, _it, _next, jsonStats); + fn.call( + m.exports, + _require, + m, + m.exports, + outputDirectory, + p, + _it, + _next, + jsonStats + ); return m.exports; } else return require(module); } _require("./bundle.js"); - if(exportedTests < 1) return done(new Error("No tests exported by test case")); + if (exportedTests < 1) + return done(new Error("No tests exported by test case")); process.nextTick(done); }); }); diff --git a/test/Integration.test.js b/test/Integration.test.js index c8ec28812..64afab276 100644 --- a/test/Integration.test.js +++ b/test/Integration.test.js @@ -7,93 +7,107 @@ const webpack = require("../lib/webpack"); describe("Integration", function() { this.timeout(5000); - it("should compile library1", (done) => { - webpack({ - mode: "production", - entry: "library1", - bail: true, - context: path.join(__dirname, "browsertest"), - output: { - pathinfo: true, - path: path.join(__dirname, "browsertest", "js"), - filename: "library1.js", - library: "library1" + it("should compile library1", done => { + webpack( + { + mode: "production", + entry: "library1", + bail: true, + context: path.join(__dirname, "browsertest"), + output: { + pathinfo: true, + path: path.join(__dirname, "browsertest", "js"), + filename: "library1.js", + library: "library1" + } + }, + (err, stats) => { + if (err) throw err; + stats.hasErrors().should.be.not.ok(); + stats.hasWarnings().should.be.not.ok(); + done(); } - }, (err, stats) => { - if(err) throw err; - stats.hasErrors().should.be.not.ok(); - stats.hasWarnings().should.be.not.ok(); - done(); - }); + ); }); - it("should compile library2", (done) => { - webpack({ - mode: "production", - entry: "library2", - context: path.join(__dirname, "browsertest"), - output: { - pathinfo: true, - path: path.join(__dirname, "browsertest", "js"), - filename: "library2.js", - publicPath: "js/", - library: "library2" - }, - bail: true, - module: { - rules: [{ - test: /extra2\.js/, - loader: "raw!extra!val?cacheable", - enforce: "post" - }] - }, - amd: { - fromOptions: true - }, - optimization: { - minimize: false - }, - resolve: { - // cannot resolve should outside the outermost node_modules - // so it is injected here - alias: { - should: require.resolve("should") - } - }, - plugins: [ - new webpack.optimize.LimitChunkCountPlugin({ - maxChunks: 1 - }), - new webpack.DefinePlugin({ - "typeof CONST_TYPEOF": JSON.stringify("typeof"), - CONST_TRUE: true, - CONST_FALSE: false, - CONST_FUNCTION: function() { - return "ok"; - }, - CONST_NUMBER: 123, - CONST_NUMBER_EXPR: "1*100+23", - CONST_OBJECT: { - A: 1, - B: JSON.stringify("B"), - C: function() { - return "C"; + it("should compile library2", done => { + webpack( + { + mode: "production", + entry: "library2", + context: path.join(__dirname, "browsertest"), + output: { + pathinfo: true, + path: path.join(__dirname, "browsertest", "js"), + filename: "library2.js", + publicPath: "js/", + library: "library2" + }, + bail: true, + module: { + rules: [ + { + test: /extra2\.js/, + loader: "raw!extra!val?cacheable", + enforce: "post" } + ] + }, + amd: { + fromOptions: true + }, + optimization: { + minimize: false + }, + resolve: { + // cannot resolve should outside the outermost node_modules + // so it is injected here + alias: { + should: require.resolve("should") } - }), - function() { - this.hooks.normalModuleFactory.tap("IntegrationTest", (nmf) => { - nmf.hooks.afterResolve.tapAsync("IntegrationTest", (data, callback) => { - data.resource = data.resource.replace(/extra\.js/, "extra2.js"); - setTimeout(() => callback(null, data), 50); + }, + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }), + new webpack.DefinePlugin({ + "typeof CONST_TYPEOF": JSON.stringify("typeof"), + CONST_TRUE: true, + CONST_FALSE: false, + CONST_FUNCTION: function() { + return "ok"; + }, + CONST_NUMBER: 123, + CONST_NUMBER_EXPR: "1*100+23", + CONST_OBJECT: { + A: 1, + B: JSON.stringify("B"), + C: function() { + return "C"; + } + } + }), + function() { + this.hooks.normalModuleFactory.tap("IntegrationTest", nmf => { + nmf.hooks.afterResolve.tapAsync( + "IntegrationTest", + (data, callback) => { + data.resource = data.resource.replace( + /extra\.js/, + "extra2.js" + ); + setTimeout(() => callback(null, data), 50); + } + ); }); - }); - } - ] - }, (err, stats) => { - if(err) throw err; - stats.hasErrors().should.be.not.ok(); - stats.hasWarnings().should.be.not.ok(); - done(); - }); + } + ] + }, + (err, stats) => { + if (err) throw err; + stats.hasErrors().should.be.not.ok(); + stats.hasWarnings().should.be.not.ok(); + done(); + } + ); }); }); diff --git a/test/LocalModulesHelpers.unittest.js b/test/LocalModulesHelpers.unittest.js index cd8a87372..b1cd88f96 100644 --- a/test/LocalModulesHelpers.unittest.js +++ b/test/LocalModulesHelpers.unittest.js @@ -5,19 +5,20 @@ const should = require("should"); const LocalModulesHelpers = require("../lib/dependencies/LocalModulesHelpers"); describe("LocalModulesHelpers", () => { - describe("addLocalModule", () => { it("returns a module var without special characters", () => { const state = { module: "module_sample", localModules: ["first", "second"] }; - should(LocalModulesHelpers.addLocalModule(state, "local_module_sample")).be.an.instanceOf(Object).and.have.properties({ - module: "module_sample", - name: "local_module_sample", - idx: 2, - used: false - }); + should(LocalModulesHelpers.addLocalModule(state, "local_module_sample")) + .be.an.instanceOf(Object) + .and.have.properties({ + module: "module_sample", + name: "local_module_sample", + idx: 2, + used: false + }); should(state.localModules.length).be.eql(3); }); }); @@ -26,28 +27,35 @@ describe("LocalModulesHelpers", () => { it("returns `null` if names information doesn't match", () => { const state = { module: "module_sample", - localModules: [{ - name: "first" - }, { - name: "second" - }] + localModules: [ + { + name: "first" + }, + { + name: "second" + } + ] }; - should(LocalModulesHelpers.getLocalModule(state, "local_module_sample")).be.eql(null); + should( + LocalModulesHelpers.getLocalModule(state, "local_module_sample") + ).be.eql(null); }); it("returns local module informtion", () => { const state = { module: "module_sample", - localModules: [{ - name: "first" - }, { - name: "second" - }] + localModules: [ + { + name: "first" + }, + { + name: "second" + } + ] }; should(LocalModulesHelpers.getLocalModule(state, "first")).be.eql({ name: "first" }); }); }); - }); diff --git a/test/ModuleDependencyError.unittest.js b/test/ModuleDependencyError.unittest.js index a485469da..cd01f0765 100644 --- a/test/ModuleDependencyError.unittest.js +++ b/test/ModuleDependencyError.unittest.js @@ -7,27 +7,41 @@ const ModuleDependencyError = require("../lib/ModuleDependencyError"); describe("ModuleDependencyError", () => { let env; - beforeEach(() => env = {}); + beforeEach(() => (env = {})); it("is a function", () => ModuleDependencyError.should.be.a.Function()); describe("when new error created", () => { beforeEach(() => { env.error = new Error("Error Message"); - env.moduleDependencyError = new ModuleDependencyError("myModule", env.error, "Location"); + env.moduleDependencyError = new ModuleDependencyError( + "myModule", + env.error, + "Location" + ); }); it("is an error", () => env.moduleDependencyError.should.be.an.Error()); - it("has a name property", () => env.moduleDependencyError.name.should.be.exactly("ModuleDependencyError")); + it("has a name property", () => + env.moduleDependencyError.name.should.be.exactly( + "ModuleDependencyError" + )); - it("has a message property", () => env.moduleDependencyError.message.should.be.exactly("Location Error Message")); + it("has a message property", () => + env.moduleDependencyError.message.should.be.exactly( + "Location Error Message" + )); - it("has a details property", () => env.moduleDependencyError.details.should.containEql(path.join("test", "ModuleDependencyError.unittest.js:"))); + it("has a details property", () => + env.moduleDependencyError.details.should.containEql( + path.join("test", "ModuleDependencyError.unittest.js:") + )); - it("has an origin property", () => env.moduleDependencyError.origin.should.be.exactly("myModule")); - - it("has an error property", () => env.moduleDependencyError.error.should.be.exactly(env.error)); + it("has an origin property", () => + env.moduleDependencyError.origin.should.be.exactly("myModule")); + it("has an error property", () => + env.moduleDependencyError.error.should.be.exactly(env.error)); }); }); diff --git a/test/ModuleReason.unittest.js b/test/ModuleReason.unittest.js index 3e80c6ae2..b72519024 100644 --- a/test/ModuleReason.unittest.js +++ b/test/ModuleReason.unittest.js @@ -23,7 +23,8 @@ describe("ModuleReason", () => { }); describe("hasChunk", () => { - it("returns false when chunk is not present", () => should(myModuleReason.hasChunk(myChunk)).be.false()); + it("returns false when chunk is not present", () => + should(myModuleReason.hasChunk(myChunk)).be.false()); it("returns true when chunk is present", () => { myModuleReason.module.addChunk(myChunk); diff --git a/test/MultiCompiler.test.js b/test/MultiCompiler.test.js index 461f89254..2f2f0dad0 100644 --- a/test/MultiCompiler.test.js +++ b/test/MultiCompiler.test.js @@ -7,13 +7,16 @@ const MemoryFs = require("memory-fs"); const webpack = require("../"); const createMultiCompiler = () => { - const compiler = webpack([{ - context: path.join(__dirname, "fixtures"), - entry: "./a.js" - }, { - context: path.join(__dirname, "fixtures"), - entry: "./b.js" - }]); + const compiler = webpack([ + { + context: path.join(__dirname, "fixtures"), + entry: "./a.js" + }, + { + context: path.join(__dirname, "fixtures"), + entry: "./b.js" + } + ]); compiler.outputFileSystem = new MemoryFs(); return compiler; }; @@ -25,7 +28,7 @@ describe("MultiCompiler", function() { compiler.hooks.run.tap("MultiCompiler test", () => called++); compiler.run(err => { - if(err) { + if (err) { throw err; } else { should(called).be.equal(2); @@ -40,7 +43,7 @@ describe("MultiCompiler", function() { compiler.hooks.watchRun.tap("MultiCompiler test", () => called++); const watcher = compiler.watch(1000, err => { - if(err) { + if (err) { throw err; } else { watcher.close(); diff --git a/test/MultiStats.unittest.js b/test/MultiStats.unittest.js index 653330bdc..ccfdb157c 100644 --- a/test/MultiStats.unittest.js +++ b/test/MultiStats.unittest.js @@ -5,20 +5,27 @@ const packageJSON = require("../package.json"); const MultiStats = require("../lib/MultiStats"); const createStat = overides => { - return Object.assign({ - hash: "foo", - compilation: { - name: "bar" - }, - hasErrors: () => false, - hasWarnings: () => false, - toJson: () => Object.assign({ + return Object.assign( + { hash: "foo", - version: "version", - warnings: [], - errors: [] - }, overides) - }, overides); + compilation: { + name: "bar" + }, + hasErrors: () => false, + hasWarnings: () => false, + toJson: () => + Object.assign( + { + hash: "foo", + version: "version", + warnings: [], + errors: [] + }, + overides + ) + }, + overides + ); }; describe("MultiStats", () => { @@ -29,7 +36,7 @@ describe("MultiStats", () => { packageJSON.version = "1.2.3"; }); - afterEach(() => packageJSON.version = packageVersion); + afterEach(() => (packageJSON.version = packageVersion)); describe("created", () => { beforeEach(() => { @@ -44,7 +51,8 @@ describe("MultiStats", () => { myMultiStats = new MultiStats(stats); }); - it("creates a hash string", () => myMultiStats.hash.should.be.exactly("abc123xyz890")); + it("creates a hash string", () => + myMultiStats.hash.should.be.exactly("abc123xyz890")); }); describe("hasErrors", () => { @@ -61,7 +69,8 @@ describe("MultiStats", () => { myMultiStats = new MultiStats(stats); }); - it("returns true", () => myMultiStats.hasErrors().should.be.exactly(true)); + it("returns true", () => + myMultiStats.hasErrors().should.be.exactly(true)); }); describe("when one has an error", () => { @@ -75,19 +84,18 @@ describe("MultiStats", () => { myMultiStats = new MultiStats(stats); }); - it("returns true", () => myMultiStats.hasErrors().should.be.exactly(true)); + it("returns true", () => + myMultiStats.hasErrors().should.be.exactly(true)); }); describe("when none have errors", () => { beforeEach(() => { - stats = [ - createStat(), - createStat() - ]; + stats = [createStat(), createStat()]; myMultiStats = new MultiStats(stats); }); - it("returns false", () => myMultiStats.hasErrors().should.be.exactly(false)); + it("returns false", () => + myMultiStats.hasErrors().should.be.exactly(false)); }); }); @@ -105,7 +113,8 @@ describe("MultiStats", () => { myMultiStats = new MultiStats(stats); }); - it("returns true", () => myMultiStats.hasWarnings().should.be.exactly(true)); + it("returns true", () => + myMultiStats.hasWarnings().should.be.exactly(true)); }); describe("when one has a warning", () => { @@ -119,19 +128,18 @@ describe("MultiStats", () => { myMultiStats = new MultiStats(stats); }); - it("returns true", () => myMultiStats.hasWarnings().should.be.exactly(true)); + it("returns true", () => + myMultiStats.hasWarnings().should.be.exactly(true)); }); describe("when none have warnings", () => { beforeEach(() => { - stats = [ - createStat(), - createStat() - ]; + stats = [createStat(), createStat()]; myMultiStats = new MultiStats(stats); }); - it("returns false", () => myMultiStats.hasWarnings().should.be.exactly(false)); + it("returns false", () => + myMultiStats.hasWarnings().should.be.exactly(false)); }); }); @@ -168,30 +176,22 @@ describe("MultiStats", () => { hash: false }); result.should.deepEqual({ - errors: [ - "(abc123-compilation) abc123-error" - ], + errors: ["(abc123-compilation) abc123-error"], warnings: [ "(abc123-compilation) abc123-warning", "(xyz890-compilation) xyz890-warning-1", "(xyz890-compilation) xyz890-warning-2" ], - children: [{ - errors: [ - "abc123-error" - ], + children: [ + { + errors: ["abc123-error"], name: "abc123-compilation", - warnings: [ - "abc123-warning" - ] + warnings: ["abc123-warning"] }, { errors: [], name: "xyz890-compilation", - warnings: [ - "xyz890-warning-1", - "xyz890-warning-2" - ] + warnings: ["xyz890-warning-1", "xyz890-warning-2"] } ] }); @@ -201,24 +201,20 @@ describe("MultiStats", () => { myMultiStats = new MultiStats(stats); result = myMultiStats.toJson(true); result.should.deepEqual({ - errors: [ - "(abc123-compilation) abc123-error" - ], + errors: ["(abc123-compilation) abc123-error"], warnings: [ "(abc123-compilation) abc123-warning", "(xyz890-compilation) xyz890-warning-1", "(xyz890-compilation) xyz890-warning-2" ], - children: [{ + children: [ + { warnings: ["abc123-warning"], errors: ["abc123-error"], name: "abc123-compilation" }, { - warnings: [ - "xyz890-warning-1", - "xyz890-warning-2" - ], + warnings: ["xyz890-warning-1", "xyz890-warning-2"], errors: [], name: "xyz890-compilation" } @@ -250,11 +246,11 @@ describe("MultiStats", () => { it("returns string representation", () => { result.should.be.exactly( "Hash: abc123xyz890\n" + - "Version: webpack 1.2.3\n" + - "Child abc123-compilation:\n" + - " Hash: abc123\n" + - "Child xyz890-compilation:\n" + - " Hash: xyz890" + "Version: webpack 1.2.3\n" + + "Child abc123-compilation:\n" + + " Hash: abc123\n" + + "Child xyz890-compilation:\n" + + " Hash: xyz890" ); }); }); diff --git a/test/MultiWatching.unittest.js b/test/MultiWatching.unittest.js index 20cbd9d51..e5b41ba99 100644 --- a/test/MultiWatching.unittest.js +++ b/test/MultiWatching.unittest.js @@ -43,7 +43,8 @@ describe("MultiWatching", () => { describe("close", () => { let callback; - const callClosedFinishedCallback = (watching) => watching.close.getCall(0).args[0](); + const callClosedFinishedCallback = watching => + watching.close.getCall(0).args[0](); beforeEach(() => { callback = sinon.spy(); diff --git a/test/NodeTemplatePlugin.test.js b/test/NodeTemplatePlugin.test.js index 0f50e41ca..473a4e19b 100644 --- a/test/NodeTemplatePlugin.test.js +++ b/test/NodeTemplatePlugin.test.js @@ -7,78 +7,82 @@ const path = require("path"); const webpack = require("../lib/webpack"); describe("NodeTemplatePlugin", () => { - - it("should compile and run a simple module", (done) => { - webpack({ - mode: "production", - context: path.join(__dirname, "fixtures", "nodetest"), - target: "node", - output: { - path: path.join(__dirname, "js"), - filename: "result.js", - chunkFilename: "[hash].result.[id].js", - library: "abc", - libraryTarget: "commonjs", + it("should compile and run a simple module", done => { + webpack( + { + mode: "production", + context: path.join(__dirname, "fixtures", "nodetest"), + target: "node", + output: { + path: path.join(__dirname, "js"), + filename: "result.js", + chunkFilename: "[hash].result.[id].js", + library: "abc", + libraryTarget: "commonjs" + }, + entry: "./entry" }, - entry: "./entry" - }, (err, stats) => { - if(err) return err; - stats.hasErrors().should.be.not.ok(); - stats.hasWarnings().should.be.not.ok(); - // eslint-disable-next-line node/no-missing-require - const result = require("./js/result").abc; - result.nextTick.should.be.equal(process.nextTick); - result.fs.should.be.equal(require("fs")); - result.loadChunk(456, (chunk) => { - chunk.should.be.eql(123); - result.loadChunk(567, (chunk) => { - chunk.should.be.eql({ - a: 1 + (err, stats) => { + if (err) return err; + stats.hasErrors().should.be.not.ok(); + stats.hasWarnings().should.be.not.ok(); + // eslint-disable-next-line node/no-missing-require + const result = require("./js/result").abc; + result.nextTick.should.be.equal(process.nextTick); + result.fs.should.be.equal(require("fs")); + result.loadChunk(456, chunk => { + chunk.should.be.eql(123); + result.loadChunk(567, chunk => { + chunk.should.be.eql({ + a: 1 + }); + done(); }); - done(); }); - }); - }); + } + ); }); - it("should compile and run a simple module in single mode", (done) => { - webpack({ - mode: "production", - context: path.join(__dirname, "fixtures", "nodetest"), - target: "node", - output: { - path: path.join(__dirname, "js"), - filename: "result2.js", - chunkFilename: "[hash].result2.[id].js", - library: "def", - libraryTarget: "umd", - auxiliaryComment: "test" + it("should compile and run a simple module in single mode", done => { + webpack( + { + mode: "production", + context: path.join(__dirname, "fixtures", "nodetest"), + target: "node", + output: { + path: path.join(__dirname, "js"), + filename: "result2.js", + chunkFilename: "[hash].result2.[id].js", + library: "def", + libraryTarget: "umd", + auxiliaryComment: "test" + }, + entry: "./entry", + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }) + ] }, - entry: "./entry", - plugins: [ - new webpack.optimize.LimitChunkCountPlugin({ - maxChunks: 1 - }) - ] - }, (err, stats) => { - if(err) return err; - stats.hasErrors().should.be.not.ok(); - // eslint-disable-next-line node/no-missing-require - const result = require("./js/result2"); - result.nextTick.should.be.equal(process.nextTick); - result.fs.should.be.equal(require("fs")); - const sameTick = true; - result.loadChunk(456, (chunk) => { - chunk.should.be.eql(123); - sameTick.should.be.eql(true); - result.loadChunk(567, (chunk) => { - chunk.should.be.eql({ - a: 1 + (err, stats) => { + if (err) return err; + stats.hasErrors().should.be.not.ok(); + // eslint-disable-next-line node/no-missing-require + const result = require("./js/result2"); + result.nextTick.should.be.equal(process.nextTick); + result.fs.should.be.equal(require("fs")); + const sameTick = true; + result.loadChunk(456, chunk => { + chunk.should.be.eql(123); + sameTick.should.be.eql(true); + result.loadChunk(567, chunk => { + chunk.should.be.eql({ + a: 1 + }); + done(); }); - done(); }); - }); - }); + } + ); }); - }); diff --git a/test/NodeWatchFileSystem.unittest.js b/test/NodeWatchFileSystem.unittest.js index f9e43c7bd..79590bed9 100644 --- a/test/NodeWatchFileSystem.unittest.js +++ b/test/NodeWatchFileSystem.unittest.js @@ -42,11 +42,19 @@ describe("NodeWatchFileSystem", function() { it("should throw if 'callbackUndelayed' argument is invalid", function() { should(function() { - new NodeWatchFileSystem().watch([], [], [], 42, {}, function() {}, "undefined"); + new NodeWatchFileSystem().watch( + [], + [], + [], + 42, + {}, + function() {}, + "undefined" + ); }).throw("Invalid arguments: 'callbackUndelayed'"); }); - if(process.env.NO_WATCH_TESTS) { + if (process.env.NO_WATCH_TESTS) { it("long running tests excluded"); return; } @@ -62,16 +70,29 @@ describe("NodeWatchFileSystem", function() { it("should register a file change (change delayed)", function(done) { var startTime = new Date().getTime(); var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([fileDirect], [], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps) { - if(err) throw err; - filesModified.should.be.eql([fileDirect]); - dirsModified.should.be.eql([]); - (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); - watcher.close(); - done(); - }); + var watcher = wfs.watch( + [fileDirect], + [], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([fileDirect]); + dirsModified.should.be.eql([]); + (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); + watcher.close(); + done(); + } + ); setTimeout(function() { fs.writeFile(fileDirect, "", function() {}); @@ -81,16 +102,29 @@ describe("NodeWatchFileSystem", function() { var startTime = new Date().getTime(); setTimeout(function() { var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([fileDirect], [], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps) { - if(err) throw err; - filesModified.should.be.eql([fileDirect]); - dirsModified.should.be.eql([]); - (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); - watcher.close(); - done(); - }); + var watcher = wfs.watch( + [fileDirect], + [], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([fileDirect]); + dirsModified.should.be.eql([]); + (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); + watcher.close(); + done(); + } + ); }, 500); fs.writeFile(fileDirect, "", function() {}); @@ -98,16 +132,30 @@ describe("NodeWatchFileSystem", function() { it("should register a context change (change delayed)", function(done) { var startTime = new Date().getTime(); var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([], [fixtures], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps, dirTimestamps) { - if(err) throw err; - filesModified.should.be.eql([]); - dirsModified.should.be.eql([fixtures]); - (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); - watcher.close(); - done(); - }); + var watcher = wfs.watch( + [], + [fixtures], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps, + dirTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([]); + dirsModified.should.be.eql([fixtures]); + (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); + watcher.close(); + done(); + } + ); setTimeout(function() { fs.writeFile(fileDirect, "", function() {}); @@ -117,52 +165,98 @@ describe("NodeWatchFileSystem", function() { var startTime = new Date().getTime(); setTimeout(function() { var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([], [fixtures], [], startTime, { + var watcher = wfs.watch( + [], + [fixtures], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps, + dirTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([]); + dirsModified.should.be.eql([fixtures]); + (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); + watcher.close(); + done(); + } + ); + }, 500); + + fs.writeFile(fileDirect, "", function() {}); + }); + it("should register a context change (change delayed, subdirectory)", function( + done + ) { + var startTime = new Date().getTime(); + var wfs = new NodeWatchFileSystem(); + var watcher = wfs.watch( + [], + [fixtures], + [], + startTime, + { aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps, dirTimestamps) { - if(err) throw err; + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps, + dirTimestamps + ) { + if (err) throw err; filesModified.should.be.eql([]); dirsModified.should.be.eql([fixtures]); (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); watcher.close(); done(); - }); - }, 500); - - fs.writeFile(fileDirect, "", function() {}); - }); - it("should register a context change (change delayed, subdirectory)", function(done) { - var startTime = new Date().getTime(); - var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([], [fixtures], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps, dirTimestamps) { - if(err) throw err; - filesModified.should.be.eql([]); - dirsModified.should.be.eql([fixtures]); - (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); - watcher.close(); - done(); - }); + } + ); setTimeout(function() { fs.writeFile(fileSubdir, "", function() {}); }, 500); }); - it("should register a context change (watch delayed, subdirectory)", function(done) { + it("should register a context change (watch delayed, subdirectory)", function( + done + ) { var startTime = new Date().getTime(); setTimeout(function() { var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([], [fixtures], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps, dirTimestamps) { - if(err) throw err; - filesModified.should.be.eql([]); - dirsModified.should.be.eql([fixtures]); - (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); - watcher.close(); - done(); - }); + var watcher = wfs.watch( + [], + [fixtures], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps, + dirTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([]); + dirsModified.should.be.eql([fixtures]); + (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); + watcher.close(); + done(); + } + ); }, 500); fs.writeFile(fileSubdir, "", function() {}); @@ -171,18 +265,32 @@ describe("NodeWatchFileSystem", function() { var startTime = new Date().getTime(); setTimeout(function() { var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([fileDirect, fileSubdir], [fixtures], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps, dirTimestamps) { - if(err) throw err; - filesModified.should.be.eql([fileSubdir, fileDirect]); - dirsModified.should.be.eql([fixtures]); - (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); - (typeof fileTimestamps.get(fileSubdir)).should.be.eql("number"); - (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); - watcher.close(); - done(); - }); + var watcher = wfs.watch( + [fileDirect, fileSubdir], + [fixtures], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps, + dirTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([fileSubdir, fileDirect]); + dirsModified.should.be.eql([fixtures]); + (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); + (typeof fileTimestamps.get(fileSubdir)).should.be.eql("number"); + (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); + watcher.close(); + done(); + } + ); }, 500); fs.writeFile(fileDirect, "", function() {}); @@ -191,18 +299,32 @@ describe("NodeWatchFileSystem", function() { it("should sum up multiple changes", function(done) { var startTime = new Date().getTime(); var wfs = new NodeWatchFileSystem(); - var watcher = wfs.watch([fileDirect, fileSubdir], [fixtures], [], startTime, { - aggregateTimeout: 1000 - }, function(err, filesModified, dirsModified, missingCreated, fileTimestamps, dirTimestamps) { - if(err) throw err; - filesModified.should.be.eql([fileSubdir, fileDirect]); - dirsModified.should.be.eql([fixtures]); - (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); - (typeof fileTimestamps.get(fileSubdir)).should.be.eql("number"); - (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); - watcher.close(); - done(); - }); + var watcher = wfs.watch( + [fileDirect, fileSubdir], + [fixtures], + [], + startTime, + { + aggregateTimeout: 1000 + }, + function( + err, + filesModified, + dirsModified, + missingCreated, + fileTimestamps, + dirTimestamps + ) { + if (err) throw err; + filesModified.should.be.eql([fileSubdir, fileDirect]); + dirsModified.should.be.eql([fixtures]); + (typeof fileTimestamps.get(fileDirect)).should.be.eql("number"); + (typeof fileTimestamps.get(fileSubdir)).should.be.eql("number"); + (typeof dirTimestamps.get(fixtures)).should.be.eql("number"); + watcher.close(); + done(); + } + ); setTimeout(function() { fs.writeFile(fileDirect, "", function() {}); diff --git a/test/NormalModule.unittest.js b/test/NormalModule.unittest.js index 3b272b4f5..eb5afce61 100644 --- a/test/NormalModule.unittest.js +++ b/test/NormalModule.unittest.js @@ -65,13 +65,16 @@ describe("NormalModule", function() { describe("#libIdent", function() { it("contextifies the userRequest of the module", function() { - normalModule.libIdent({ - context: "some/context" - }).should.eql("../userRequest"); + normalModule + .libIdent({ + context: "some/context" + }) + .should.eql("../userRequest"); }); describe("given a userRequest containing loaders", function() { beforeEach(function() { - userRequest = "some/userRequest!some/other/userRequest!some/thing/is/off/here"; + userRequest = + "some/userRequest!some/other/userRequest!some/thing/is/off/here"; normalModule = new NormalModule({ type: "javascript/auto", request, @@ -83,14 +86,19 @@ describe("NormalModule", function() { }); }); it("contextifies every path in the userRequest", function() { - normalModule.libIdent({ - context: "some/context" - }).should.eql("../userRequest!../other/userRequest!../thing/is/off/here"); + normalModule + .libIdent({ + context: "some/context" + }) + .should.eql( + "../userRequest!../other/userRequest!../thing/is/off/here" + ); }); }); describe("given a userRequest containing query parameters", function() { it("ignores paths in query parameters", function() { - userRequest = "some/context/loader?query=foo\\bar&otherPath=testpath/other"; + userRequest = + "some/context/loader?query=foo\\bar&otherPath=testpath/other"; normalModule = new NormalModule({ type: "javascript/auto", request, @@ -100,9 +108,11 @@ describe("NormalModule", function() { resource, parser }); - normalModule.libIdent({ - context: "some/context", - }).should.eql("./loader?query=foo\\bar&otherPath=testpath/other"); + normalModule + .libIdent({ + context: "some/context" + }) + .should.eql("./loader?query=foo\\bar&otherPath=testpath/other"); }); }); }); @@ -142,12 +152,16 @@ describe("NormalModule", function() { }); describe("given no sourcemap", function() { it("returns a RawSource", function() { - normalModule.createSourceForAsset(name, content).should.be.instanceOf(RawSource); + normalModule + .createSourceForAsset(name, content) + .should.be.instanceOf(RawSource); }); }); describe("given a string as the sourcemap", function() { it("returns a OriginalSource", function() { - normalModule.createSourceForAsset(name, content, sourceMap).should.be.instanceOf(OriginalSource); + normalModule + .createSourceForAsset(name, content, sourceMap) + .should.be.instanceOf(OriginalSource); }); }); describe("given a some other kind of sourcemap", function() { @@ -155,7 +169,9 @@ describe("NormalModule", function() { sourceMap = () => {}; }); it("returns a SourceMapSource", function() { - normalModule.createSourceForAsset(name, content, sourceMap).should.be.instanceOf(SourceMapSource); + normalModule + .createSourceForAsset(name, content, sourceMap) + .should.be.instanceOf(SourceMapSource); }); }); }); @@ -183,7 +199,7 @@ describe("NormalModule", function() { beforeEach(function() { normalModule._source = null; }); - it("calls hash function with \"null\"", function() { + it('calls hash function with "null"', function() { normalModule.updateHashWithSource(hash); hashSpy.callCount.should.eql(1); hashSpy.args[0][0].should.eql("null"); @@ -194,7 +210,7 @@ describe("NormalModule", function() { beforeEach(function() { normalModule._source = new RawSource(expectedSource); }); - it("calls hash function with \"source\" and then the actual source of the module", function() { + it('calls hash function with "source" and then the actual source of the module', function() { normalModule.updateHashWithSource(hash); hashSpy.callCount.should.eql(2); hashSpy.args[0][0].should.eql("source"); @@ -219,9 +235,7 @@ describe("NormalModule", function() { let fileA; let fileB; - function setDeps( - fileDependencies, - contextDependencies) { + function setDeps(fileDependencies, contextDependencies) { normalModule.buildInfo.fileDependencies = fileDependencies; normalModule.buildInfo.contextDependencies = contextDependencies; } @@ -231,20 +245,16 @@ describe("NormalModule", function() { fileB = "fileB"; fileDependencies = [fileA, fileB]; contextDependencies = [fileA, fileB]; - fileTimestamps = new Map([ - [fileA, 1], - [fileB, 1] - ]); - contextTimestamps = new Map([ - [fileA, 1], - [fileB, 1], - ]); + fileTimestamps = new Map([[fileA, 1], [fileB, 1]]); + contextTimestamps = new Map([[fileA, 1], [fileB, 1]]); normalModule.buildTimestamp = 2; setDeps(fileDependencies, contextDependencies); }); describe("given all timestamps are older than the buildTimestamp", function() { it("returns false", function() { - normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(false); + normalModule + .needRebuild(fileTimestamps, contextTimestamps) + .should.eql(false); }); }); describe("given a file timestamp is newer than the buildTimestamp", function() { @@ -252,7 +262,9 @@ describe("NormalModule", function() { fileTimestamps.set(fileA, 3); }); it("returns true", function() { - normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true); + normalModule + .needRebuild(fileTimestamps, contextTimestamps) + .should.eql(true); }); }); describe("given a no file timestamp exists", function() { @@ -260,7 +272,9 @@ describe("NormalModule", function() { fileTimestamps = new Map(); }); it("returns true", function() { - normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true); + normalModule + .needRebuild(fileTimestamps, contextTimestamps) + .should.eql(true); }); }); describe("given a context timestamp is newer than the buildTimestamp", function() { @@ -268,7 +282,9 @@ describe("NormalModule", function() { contextTimestamps.set(fileA, 3); }); it("returns true", function() { - normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true); + normalModule + .needRebuild(fileTimestamps, contextTimestamps) + .should.eql(true); }); }); describe("given a no context timestamp exists", function() { @@ -276,7 +292,9 @@ describe("NormalModule", function() { contextTimestamps = new Map(); }); it("returns true", function() { - normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true); + normalModule + .needRebuild(fileTimestamps, contextTimestamps) + .should.eql(true); }); }); }); @@ -348,13 +366,17 @@ describe("NormalModule", function() { }); describe("that is a string", function() { it("calls and returns whatever applyNoParseRule returns", function() { - normalModule.shouldPreventParsing("some rule").should.eql(returnValOfSpy); + normalModule + .shouldPreventParsing("some rule") + .should.eql(returnValOfSpy); applyNoParseRuleSpy.callCount.should.eql(1); }); }); describe("that is a regex", function() { it("calls and returns whatever applyNoParseRule returns", function() { - normalModule.shouldPreventParsing("some rule").should.eql(returnValOfSpy); + normalModule + .shouldPreventParsing("some rule") + .should.eql(returnValOfSpy); applyNoParseRuleSpy.callCount.should.eql(1); }); }); @@ -362,11 +384,7 @@ describe("NormalModule", function() { describe("of strings and or regexs", function() { let someRules; beforeEach(function() { - someRules = [ - "some rule", - /some rule1/, - "some rule2", - ]; + someRules = ["some rule", /some rule1/, "some rule2"]; }); describe("and none of them match", function() { beforeEach(function() { @@ -374,7 +392,9 @@ describe("NormalModule", function() { applyNoParseRuleSpy.returns(returnValOfSpy); }); it("returns false", function() { - normalModule.shouldPreventParsing(someRules).should.eql(returnValOfSpy); + normalModule + .shouldPreventParsing(someRules) + .should.eql(returnValOfSpy); applyNoParseRuleSpy.callCount.should.eql(3); }); }); @@ -384,7 +404,9 @@ describe("NormalModule", function() { applyNoParseRuleSpy.returns(returnValOfSpy); }); it("returns true", function() { - normalModule.shouldPreventParsing(someRules).should.eql(returnValOfSpy); + normalModule + .shouldPreventParsing(someRules) + .should.eql(returnValOfSpy); applyNoParseRuleSpy.callCount.should.eql(1); }); }); @@ -396,7 +418,9 @@ describe("NormalModule", function() { applyNoParseRuleSpy.onCall(2).returns(true); }); it("returns true", function() { - normalModule.shouldPreventParsing(someRules).should.eql(returnValOfSpy); + normalModule + .shouldPreventParsing(someRules) + .should.eql(returnValOfSpy); applyNoParseRuleSpy.callCount.should.eql(3); }); }); diff --git a/test/NullDependency.unittest.js b/test/NullDependency.unittest.js index 5f6f1f5eb..d8862ed38 100644 --- a/test/NullDependency.unittest.js +++ b/test/NullDependency.unittest.js @@ -7,16 +7,18 @@ const NullDependency = require("../lib/dependencies/NullDependency"); describe("NullDependency", () => { let env; - beforeEach(() => env = {}); + beforeEach(() => (env = {})); it("is a function", () => NullDependency.should.be.a.Function()); describe("when created", () => { - beforeEach(() => env.nullDependency = new NullDependency()); + beforeEach(() => (env.nullDependency = new NullDependency())); - it("has a null type", () => env.nullDependency.type.should.be.exactly("null")); + it("has a null type", () => + env.nullDependency.type.should.be.exactly("null")); - it("has update hash function", () => env.nullDependency.updateHash.should.be.Function()); + it("has update hash function", () => + env.nullDependency.updateHash.should.be.Function()); it("does not update hash", () => { const hash = { @@ -31,9 +33,12 @@ describe("NullDependency", () => { it("is a function", () => NullDependency.Template.should.be.a.Function()); describe("when created", () => { - beforeEach(() => env.nullDependencyTemplate = new NullDependency.Template()); + beforeEach( + () => (env.nullDependencyTemplate = new NullDependency.Template()) + ); - it("has apply function", () => env.nullDependencyTemplate.apply.should.be.Function()); + it("has apply function", () => + env.nullDependencyTemplate.apply.should.be.Function()); }); }); }); diff --git a/test/Parser.unittest.js b/test/Parser.unittest.js index 329017834..54308af2e 100644 --- a/test/Parser.unittest.js +++ b/test/Parser.unittest.js @@ -13,49 +13,56 @@ describe("Parser", () => { "call ident": [ function() { abc("test"); - }, { + }, + { abc: ["test"] } ], "call member": [ function() { cde.abc("membertest"); - }, { + }, + { cdeabc: ["membertest"] } ], "call member using bracket notation": [ function() { cde["abc"]("membertest"); - }, { + }, + { cdeabc: ["membertest"] } ], "call inner member": [ function() { cde.ddd.abc("inner"); - }, { + }, + { cdedddabc: ["inner"] } ], "call inner member using bracket notation": [ function() { cde.ddd["abc"]("inner"); - }, { + }, + { cdedddabc: ["inner"] } ], - "expression": [ + expression: [ function() { fgh; - }, { + }, + { fgh: [""] } ], "expression sub": [ function() { fgh.sub; - }, { + }, + { fghsub: ["notry"] } ], @@ -63,7 +70,8 @@ describe("Parser", () => { function() { test[memberExpr]; test[+memberExpr]; - }, { + }, + { expressions: ["memberExpr", "memberExpr"] } ], @@ -76,7 +84,8 @@ describe("Parser", () => { fgh; fgh.sub; })(); - }, {} + }, + {} ], "const definition": [ function() { @@ -86,7 +95,8 @@ describe("Parser", () => { cde.ddd.abc("test"); fgh; fgh.sub; - }, {} + }, + {} ], "var definition": [ function() { @@ -96,7 +106,8 @@ describe("Parser", () => { cde.ddd.abc("test"); fgh; fgh.sub; - }, {} + }, + {} ], "function definition": [ function() { @@ -110,7 +121,8 @@ describe("Parser", () => { cde.ddd.abc("test"); fgh; fgh.sub; - }, {} + }, + {} ], "class definition": [ function() { @@ -123,7 +135,8 @@ describe("Parser", () => { fgh(); } } - }, { + }, + { abc: ["cde", "fgh"], fgh: ["memberExpr"] } @@ -138,11 +151,12 @@ describe("Parser", () => { fgh.sub; fgh; } - } catch(e) { + } catch (e) { fgh.sub; fgh; } - }, { + }, + { fghsub: ["try", "notry", "notry"], fgh: ["test", "test ttt", "test e"] } @@ -151,7 +165,8 @@ describe("Parser", () => { function() { const xyz = abc; xyz("test"); - }, { + }, + { abc: ["test"] } ], @@ -159,7 +174,8 @@ describe("Parser", () => { function() { var xyz = abc; xyz("test"); - }, { + }, + { abc: ["test"] } ], @@ -167,53 +183,59 @@ describe("Parser", () => { function() { const xyz = abc; xyz("test"); - }, { + }, + { abc: ["test"] } ], "renaming with IIFE": [ function() { - ! function(xyz) { + !(function(xyz) { xyz("test"); - }(abc); - }, { + })(abc); + }, + { abc: ["test"] } ], "renaming arguments with IIFE (called)": [ function() { - ! function(xyz) { + !function(xyz) { xyz("test"); }.call(fgh, abc); - }, { + }, + { abc: ["test"], fgh: [""] } ], "renaming this's properties with IIFE (called)": [ function() { - ! function() { + !function() { this.sub; }.call(ijk); - }, { + }, + { ijksub: ["test"] } ], "renaming this's properties with nested IIFE (called)": [ function() { - ! function() { - ! function() { + !function() { + !function() { this.sub; }.call(this); }.call(ijk); - }, { + }, + { ijksub: ["test"] } ], "new Foo(...)": [ function() { new xyz("membertest"); - }, { + }, + { xyz: ["membertest"] } ], @@ -221,7 +243,8 @@ describe("Parser", () => { function() { var xyz = [...abc("xyz"), cde]; Math.max(...fgh); - }, { + }, + { abc: ["xyz"], fgh: ["xyz"] } @@ -231,52 +254,56 @@ describe("Parser", () => { /* eslint-enable no-unused-vars */ /* eslint-enable no-inner-declarations */ - Object.keys(testCases).forEach((name) => { + Object.keys(testCases).forEach(name => { it("should parse " + name, () => { let source = testCases[name][0].toString(); source = source.substr(13, source.length - 14).trim(); const state = testCases[name][1]; const testParser = new Parser({}); - testParser.hooks.canRename.tap("abc", "ParserTest", (expr) => true); - testParser.hooks.canRename.tap("ijk", "ParserTest", (expr) => true); - testParser.hooks.call.tap("abc", "ParserTest", (expr) => { - if(!testParser.state.abc) testParser.state.abc = []; + testParser.hooks.canRename.tap("abc", "ParserTest", expr => true); + testParser.hooks.canRename.tap("ijk", "ParserTest", expr => true); + testParser.hooks.call.tap("abc", "ParserTest", expr => { + if (!testParser.state.abc) testParser.state.abc = []; testParser.state.abc.push(testParser.parseString(expr.arguments[0])); return true; }); - testParser.hooks.call.tap("cde.abc", "ParserTest", (expr) => { - if(!testParser.state.cdeabc) testParser.state.cdeabc = []; + testParser.hooks.call.tap("cde.abc", "ParserTest", expr => { + if (!testParser.state.cdeabc) testParser.state.cdeabc = []; testParser.state.cdeabc.push(testParser.parseString(expr.arguments[0])); return true; }); - testParser.hooks.call.tap("cde.ddd.abc", "ParserTest", (expr) => { - if(!testParser.state.cdedddabc) testParser.state.cdedddabc = []; - testParser.state.cdedddabc.push(testParser.parseString(expr.arguments[0])); + testParser.hooks.call.tap("cde.ddd.abc", "ParserTest", expr => { + if (!testParser.state.cdedddabc) testParser.state.cdedddabc = []; + testParser.state.cdedddabc.push( + testParser.parseString(expr.arguments[0]) + ); return true; }); - testParser.hooks.expression.tap("fgh", "ParserTest", (expr) => { - if(!testParser.state.fgh) testParser.state.fgh = []; - testParser.state.fgh.push(Array.from(testParser.scope.definitions.asSet()).join(" ")); + testParser.hooks.expression.tap("fgh", "ParserTest", expr => { + if (!testParser.state.fgh) testParser.state.fgh = []; + testParser.state.fgh.push( + Array.from(testParser.scope.definitions.asSet()).join(" ") + ); return true; }); - testParser.hooks.expression.tap("fgh.sub", "ParserTest", (expr) => { - if(!testParser.state.fghsub) testParser.state.fghsub = []; + testParser.hooks.expression.tap("fgh.sub", "ParserTest", expr => { + if (!testParser.state.fghsub) testParser.state.fghsub = []; testParser.state.fghsub.push(testParser.scope.inTry ? "try" : "notry"); return true; }); - testParser.hooks.expression.tap("ijk.sub", "ParserTest", (expr) => { - if(!testParser.state.ijksub) testParser.state.ijksub = []; + testParser.hooks.expression.tap("ijk.sub", "ParserTest", expr => { + if (!testParser.state.ijksub) testParser.state.ijksub = []; testParser.state.ijksub.push("test"); return true; }); - testParser.hooks.expression.tap("memberExpr", "ParserTest", (expr) => { - if(!testParser.state.expressions) testParser.state.expressions = []; + testParser.hooks.expression.tap("memberExpr", "ParserTest", expr => { + if (!testParser.state.expressions) testParser.state.expressions = []; testParser.state.expressions.push(expr.name); return true; }); - testParser.hooks.new.tap("xyz", "ParserTest", (expr) => { - if(!testParser.state.xyz) testParser.state.xyz = []; + testParser.hooks.new.tap("xyz", "ParserTest", expr => { + if (!testParser.state.xyz) testParser.state.xyz = []; testParser.state.xyz.push(testParser.parseString(expr.arguments[0])); return true; }); @@ -288,18 +315,21 @@ describe("Parser", () => { it("should parse comments", () => { const source = "//comment1\n/*comment2*/"; - const state = [{ - type: "Line", - value: "comment1" - }, { - type: "Block", - value: "comment2" - }]; + const state = [ + { + type: "Line", + value: "comment1" + }, + { + type: "Block", + value: "comment2" + } + ]; const testParser = new Parser({}); testParser.hooks.program.tap("ParserTest", (ast, comments) => { - if(!testParser.state.comments) testParser.state.comments = comments; + if (!testParser.state.comments) testParser.state.comments = comments; return true; }); @@ -317,20 +347,22 @@ describe("Parser", () => { describe("expression evaluation", () => { function evaluateInParser(source) { const parser = new Parser(); - parser.hooks.call.tap("test", "ParserTest", (expr) => { + parser.hooks.call.tap("test", "ParserTest", expr => { parser.state.result = parser.evaluateExpression(expr.arguments[0]); }); - parser.hooks.evaluateIdentifier.tap("aString", "ParserTest", (expr) => - new BasicEvaluatedExpression().setString("aString").setRange(expr.range)); - parser.hooks.evaluateIdentifier.tap("b.Number", "ParserTest", (expr) => - new BasicEvaluatedExpression().setNumber(123).setRange(expr.range)); + parser.hooks.evaluateIdentifier.tap("aString", "ParserTest", expr => + new BasicEvaluatedExpression().setString("aString").setRange(expr.range) + ); + parser.hooks.evaluateIdentifier.tap("b.Number", "ParserTest", expr => + new BasicEvaluatedExpression().setNumber(123).setRange(expr.range) + ); return parser.parse("test(" + source + ");").result; } const testCases = { - "\"strrring\"": "string=strrring", - "\"strr\" + \"ring\"": "string=strrring", - "\"s\" + (\"trr\" + \"rin\") + \"g\"": "string=strrring", + '"strrring"': "string=strrring", + '"strr" + "ring"': "string=strrring", + '"s" + ("trr" + "rin") + "g"': "string=strrring", "'S' + (\"strr\" + \"ring\") + 'y'": "string=Sstrrringy", "/abc/": "regExp=/abc/", "1": "number=1", @@ -368,14 +400,21 @@ describe("Parser", () => { "'' + 1 + a + 2": "wrapped=['' + 1 string=1]+[2 string=2]", "'' + 1 + a + 2 + 3": "wrapped=['' + 1 string=1]+[2 + 3 string=23]", "'' + 1 + a + (2 + 3)": "wrapped=['' + 1 string=1]+[2 + 3 string=5]", - "'pre' + (1 + a) + (2 + 3)": "wrapped=['pre' string=pre]+[2 + 3 string=5]", + "'pre' + (1 + a) + (2 + 3)": + "wrapped=['pre' string=pre]+[2 + 3 string=5]", "a ? 'o1' : 'o2'": "options=['o1' string=o1],['o2' string=o2]", - "a ? 'o1' : b ? 'o2' : 'o3'": "options=['o1' string=o1],['o2' string=o2],['o3' string=o3]", - "a ? (b ? 'o1' : 'o2') : 'o3'": "options=['o1' string=o1],['o2' string=o2],['o3' string=o3]", - "a ? (b ? 'o1' : 'o2') : c ? 'o3' : 'o4'": "options=['o1' string=o1],['o2' string=o2],['o3' string=o3],['o4' string=o4]", - "a ? 'o1' : b ? 'o2' : c ? 'o3' : 'o4'": "options=['o1' string=o1],['o2' string=o2],['o3' string=o3],['o4' string=o4]", - "a ? 'o1' : b ? b : c ? 'o3' : c": "options=['o1' string=o1],[b],['o3' string=o3],[c]", - "['i1', 'i2', 3, a, b ? 4 : 5]": "items=['i1' string=i1],['i2' string=i2],[3 number=3],[a],[b ? 4 : 5 options=[4 number=4],[5 number=5]]", + "a ? 'o1' : b ? 'o2' : 'o3'": + "options=['o1' string=o1],['o2' string=o2],['o3' string=o3]", + "a ? (b ? 'o1' : 'o2') : 'o3'": + "options=['o1' string=o1],['o2' string=o2],['o3' string=o3]", + "a ? (b ? 'o1' : 'o2') : c ? 'o3' : 'o4'": + "options=['o1' string=o1],['o2' string=o2],['o3' string=o3],['o4' string=o4]", + "a ? 'o1' : b ? 'o2' : c ? 'o3' : 'o4'": + "options=['o1' string=o1],['o2' string=o2],['o3' string=o3],['o4' string=o4]", + "a ? 'o1' : b ? b : c ? 'o3' : c": + "options=['o1' string=o1],[b],['o3' string=o3],[c]", + "['i1', 'i2', 3, a, b ? 4 : 5]": + "items=['i1' string=i1],['i2' string=i2],[3 number=3],[a],[b ? 4 : 5 options=[4 number=4],[5 number=5]]", "typeof 'str'": "string=string", "typeof aString": "string=string", "typeof b.Number": "string=number", @@ -390,33 +429,56 @@ describe("Parser", () => { "'str'.concat('one').concat('two', 'three')": "string=stronetwothree", "'str'.concat('one', 'two')": "string=stronetwo", "'str'.concat('one', 'two').concat('three')": "string=stronetwothree", - "'str'.concat('one', 'two').concat('three', 'four')": "string=stronetwothreefour", + "'str'.concat('one', 'two').concat('three', 'four')": + "string=stronetwothreefour", "'str'.concat('one', obj)": "wrapped=['str' string=str]+[null]", "'str'.concat('one', obj).concat()": "wrapped=['str' string=str]+[null]", - "'str'.concat('one', obj, 'two')": "wrapped=['str' string=str]+['two' string=two]", - "'str'.concat('one', obj, 'two').concat()": "wrapped=['str' string=str]+['two' string=two]", - "'str'.concat('one', obj, 'two').concat('three')": "wrapped=['str' string=str]+['three' string=three]", + "'str'.concat('one', obj, 'two')": + "wrapped=['str' string=str]+['two' string=two]", + "'str'.concat('one', obj, 'two').concat()": + "wrapped=['str' string=str]+['two' string=two]", + "'str'.concat('one', obj, 'two').concat('three')": + "wrapped=['str' string=str]+['three' string=three]", "'str'.concat(obj)": "wrapped=['str' string=str]+[null]", "'str'.concat(obj).concat()": "wrapped=['str' string=str]+[null]", - "'str'.concat(obj).concat('one', 'two')": "wrapped=['str' string=str]+['one', 'two' string=onetwo]", - "'str'.concat(obj).concat(obj, 'one')": "wrapped=['str' string=str]+['one' string=one]", - "'str'.concat(obj).concat(obj, 'one', 'two')": "wrapped=['str' string=str]+['one', 'two' string=onetwo]", - "'str'.concat(obj).concat('one', obj, 'one')": "wrapped=['str' string=str]+['one' string=one]", - "'str'.concat(obj).concat('one', obj, 'two', 'three')": "wrapped=['str' string=str]+['two', 'three' string=twothree]", - "'str'.concat(obj, 'one')": "wrapped=['str' string=str]+['one' string=one]", - "'str'.concat(obj, 'one').concat()": "wrapped=['str' string=str]+['one' string=one]", - "'str'.concat(obj, 'one').concat('two', 'three')": "wrapped=['str' string=str]+['two', 'three' string=twothree]", - "'str'.concat(obj, 'one').concat(obj, 'two', 'three')": "wrapped=['str' string=str]+['two', 'three' string=twothree]", - "'str'.concat(obj, 'one').concat('two', obj, 'three')": "wrapped=['str' string=str]+['three' string=three]", - "'str'.concat(obj, 'one').concat('two', obj, 'three', 'four')": "wrapped=['str' string=str]+['three', 'four' string=threefour]", - "'str'.concat(obj, 'one', 'two')": "wrapped=['str' string=str]+['one', 'two' string=onetwo]", - "'str'.concat(obj, 'one', 'two').concat()": "wrapped=['str' string=str]+['one', 'two' string=onetwo]", - "'str'.concat(obj, 'one', 'two').concat('three', 'four')": "wrapped=['str' string=str]+['three', 'four' string=threefour]", - "'str'.concat(obj, 'one', 'two').concat(obj, 'three', 'four')": "wrapped=['str' string=str]+['three', 'four' string=threefour]", - "'str'.concat(obj, 'one', 'two').concat('three', obj, 'four')": "wrapped=['str' string=str]+['four' string=four]", - "'str'.concat(obj, 'one', 'two').concat('three', obj, 'four', 'five')": "wrapped=['str' string=str]+['four', 'five' string=fourfive]", - "`start${obj}mid${obj2}end`": "template=[start string=start],[mid string=mid],[end string=end]", // eslint-disable-line no-template-curly-in-string - "`start${'str'}mid${obj2}end`": "template=[start${'str'}mid string=startstrmid],[end string=end]", // eslint-disable-line no-template-curly-in-string + "'str'.concat(obj).concat('one', 'two')": + "wrapped=['str' string=str]+['one', 'two' string=onetwo]", + "'str'.concat(obj).concat(obj, 'one')": + "wrapped=['str' string=str]+['one' string=one]", + "'str'.concat(obj).concat(obj, 'one', 'two')": + "wrapped=['str' string=str]+['one', 'two' string=onetwo]", + "'str'.concat(obj).concat('one', obj, 'one')": + "wrapped=['str' string=str]+['one' string=one]", + "'str'.concat(obj).concat('one', obj, 'two', 'three')": + "wrapped=['str' string=str]+['two', 'three' string=twothree]", + "'str'.concat(obj, 'one')": + "wrapped=['str' string=str]+['one' string=one]", + "'str'.concat(obj, 'one').concat()": + "wrapped=['str' string=str]+['one' string=one]", + "'str'.concat(obj, 'one').concat('two', 'three')": + "wrapped=['str' string=str]+['two', 'three' string=twothree]", + "'str'.concat(obj, 'one').concat(obj, 'two', 'three')": + "wrapped=['str' string=str]+['two', 'three' string=twothree]", + "'str'.concat(obj, 'one').concat('two', obj, 'three')": + "wrapped=['str' string=str]+['three' string=three]", + "'str'.concat(obj, 'one').concat('two', obj, 'three', 'four')": + "wrapped=['str' string=str]+['three', 'four' string=threefour]", + "'str'.concat(obj, 'one', 'two')": + "wrapped=['str' string=str]+['one', 'two' string=onetwo]", + "'str'.concat(obj, 'one', 'two').concat()": + "wrapped=['str' string=str]+['one', 'two' string=onetwo]", + "'str'.concat(obj, 'one', 'two').concat('three', 'four')": + "wrapped=['str' string=str]+['three', 'four' string=threefour]", + "'str'.concat(obj, 'one', 'two').concat(obj, 'three', 'four')": + "wrapped=['str' string=str]+['three', 'four' string=threefour]", + "'str'.concat(obj, 'one', 'two').concat('three', obj, 'four')": + "wrapped=['str' string=str]+['four' string=four]", + "'str'.concat(obj, 'one', 'two').concat('three', obj, 'four', 'five')": + "wrapped=['str' string=str]+['four', 'five' string=fourfive]", + "`start${obj}mid${obj2}end`": + "template=[start string=start],[mid string=mid],[end string=end]", // eslint-disable-line no-template-curly-in-string + "`start${'str'}mid${obj2}end`": + "template=[start${'str'}mid string=startstrmid],[end string=end]", // eslint-disable-line no-template-curly-in-string "'abc'.substr(1)": "string=bc", "'abcdef'.substr(2, 3)": "string=cde", "'abcdef'.substring(2, 3)": "string=c", @@ -428,29 +490,52 @@ describe("Parser", () => { "'a' + (expr + 'c')": "wrapped=['a' string=a]+['c' string=c]", "1 + 'a'": "string=1a", "'a' + 1": "string=a1", - "'a' + expr + 1": "wrapped=['a' string=a]+[1 string=1]", + "'a' + expr + 1": "wrapped=['a' string=a]+[1 string=1]" }; - Object.keys(testCases).forEach((key) => { - + Object.keys(testCases).forEach(key => { function evalExprToString(evalExpr) { - if(!evalExpr) { + if (!evalExpr) { return "null"; } else { const result = []; - if(evalExpr.isString()) result.push("string=" + evalExpr.string); - if(evalExpr.isNumber()) result.push("number=" + evalExpr.number); - if(evalExpr.isBoolean()) result.push("bool=" + evalExpr.bool); - if(evalExpr.isRegExp()) result.push("regExp=" + evalExpr.regExp); - if(evalExpr.isConditional()) result.push("options=[" + evalExpr.options.map(evalExprToString).join("],[") + "]"); - if(evalExpr.isArray()) result.push("items=[" + evalExpr.items.map(evalExprToString).join("],[") + "]"); - if(evalExpr.isConstArray()) result.push("array=[" + evalExpr.array.join("],[") + "]"); - if(evalExpr.isTemplateString()) result.push("template=[" + evalExpr.quasis.map(evalExprToString).join("],[") + "]"); - if(evalExpr.isWrapped()) result.push("wrapped=[" + evalExprToString(evalExpr.prefix) + "]+[" + evalExprToString(evalExpr.postfix) + "]"); - if(evalExpr.range) { + if (evalExpr.isString()) result.push("string=" + evalExpr.string); + if (evalExpr.isNumber()) result.push("number=" + evalExpr.number); + if (evalExpr.isBoolean()) result.push("bool=" + evalExpr.bool); + if (evalExpr.isRegExp()) result.push("regExp=" + evalExpr.regExp); + if (evalExpr.isConditional()) + result.push( + "options=[" + + evalExpr.options.map(evalExprToString).join("],[") + + "]" + ); + if (evalExpr.isArray()) + result.push( + "items=[" + evalExpr.items.map(evalExprToString).join("],[") + "]" + ); + if (evalExpr.isConstArray()) + result.push("array=[" + evalExpr.array.join("],[") + "]"); + if (evalExpr.isTemplateString()) + result.push( + "template=[" + + evalExpr.quasis.map(evalExprToString).join("],[") + + "]" + ); + if (evalExpr.isWrapped()) + result.push( + "wrapped=[" + + evalExprToString(evalExpr.prefix) + + "]+[" + + evalExprToString(evalExpr.postfix) + + "]" + ); + if (evalExpr.range) { const start = evalExpr.range[0] - 5; const end = evalExpr.range[1] - 5; - return key.substr(start, end - start) + (result.length > 0 ? " " + result.join(" ") : ""); + return ( + key.substr(start, end - start) + + (result.length > 0 ? " " + result.join(" ") : "") + ); } return result.join(" "); } @@ -458,7 +543,9 @@ describe("Parser", () => { it("should eval " + key, () => { const evalExpr = evaluateInParser(key); - evalExprToString(evalExpr).should.be.eql(testCases[key] ? key + " " + testCases[key] : key); + evalExprToString(evalExpr).should.be.eql( + testCases[key] ? key + " " + testCases[key] : key + ); }); }); }); @@ -472,7 +559,7 @@ describe("Parser", () => { "await iteration": "async function f() { for await (x of xs); }" }; const parser = new Parser(); - Object.keys(cases).forEach((name) => { + Object.keys(cases).forEach(name => { const expr = cases[name]; it(name, () => { const actual = parser.parse(expr); @@ -482,29 +569,31 @@ describe("Parser", () => { }); describe("should parse await", () => { const cases = { - "require": [ - "async function x() { await require('y'); }", { + require: [ + "async function x() { await require('y'); }", + { param: "y" } ], - "import": [ - "async function x() { const y = await import('z'); }", { + import: [ + "async function x() { const y = await import('z'); }", + { param: "z" } ] }; const parser = new Parser(); - parser.hooks.call.tap("require", "ParserTest", (expr) => { + parser.hooks.call.tap("require", "ParserTest", expr => { const param = parser.evaluateExpression(expr.arguments[0]); parser.state.param = param.string; }); - parser.hooks.importCall.tap("ParserTest", (expr) => { + parser.hooks.importCall.tap("ParserTest", expr => { const param = parser.evaluateExpression(expr.arguments[0]); parser.state.param = param.string; }); - Object.keys(cases).forEach((name) => { + Object.keys(cases).forEach(name => { it(name, () => { const actual = parser.parse(cases[name][0]); actual.should.be.eql(cases[name][1]); @@ -519,7 +608,7 @@ describe("Parser", () => { "object spread": "({...obj})", "object rest": "({...obj} = foo)" }; - Object.keys(cases).forEach((name) => { + Object.keys(cases).forEach(name => { const expr = cases[name]; it(name, () => { const actual = Parser.parse(expr); diff --git a/test/ProfilingPlugin.unittest.js b/test/ProfilingPlugin.unittest.js index 9698f185e..f0b97a772 100644 --- a/test/ProfilingPlugin.unittest.js +++ b/test/ProfilingPlugin.unittest.js @@ -16,47 +16,59 @@ describe("Profiling Plugin", () => { plugin.outputPath.should.equal("events.json"); }); - it("should handle when unable to require the inspector", (done) => { + it("should handle when unable to require the inspector", done => { const profiler = new ProfilingPlugin.Profiler(); - profiler.startProfiling().then(() => { - done(); - }).catch(e => { - done(e); - }); + profiler + .startProfiling() + .then(() => { + done(); + }) + .catch(e => { + done(e); + }); }); - it("should handle when unable to start a profiling session", (done) => { + it("should handle when unable to start a profiling session", done => { const profiler = new ProfilingPlugin.Profiler({ Session() { throw new Error("Sean Larkin was here."); } }); - profiler.startProfiling().then(() => { - done(); - }).catch(e => { - done(e); - }); + profiler + .startProfiling() + .then(() => { + done(); + }) + .catch(e => { + done(e); + }); }); - it("handles sending a profiling message when no session", (done) => { + it("handles sending a profiling message when no session", done => { const profiler = new ProfilingPlugin.Profiler(); - profiler.sendCommand("randy", "is a puppers").then(() => { - done(); - }).catch(e => { - done(e); - }); + profiler + .sendCommand("randy", "is a puppers") + .then(() => { + done(); + }) + .catch(e => { + done(e); + }); }); - it("handles destroying when no session", (done) => { + it("handles destroying when no session", done => { const profiler = new ProfilingPlugin.Profiler(); - profiler.destroy().then(() => { - done(); - }).catch(e => { - done(e); - }); + profiler + .destroy() + .then(() => { + done(); + }) + .catch(e => { + done(e); + }); }); }); diff --git a/test/RawModule.unittest.js b/test/RawModule.unittest.js index f76a78d0f..a9b56ff26 100644 --- a/test/RawModule.unittest.js +++ b/test/RawModule.unittest.js @@ -24,15 +24,16 @@ describe("RawModule", () => { }); describe("size", () => { - it("returns value for sourceStr attribute\"s length property", () => { + it('returns value for sourceStr attribute"s length property', () => { const sourceStrLength = myRawModule.sourceStr.length; should(myRawModule.size()).be.exactly(sourceStrLength); }); }); describe("readableIdentifier", () => { - it("returns result of calling provided requestShortener\"s shorten method " + - "on readableIdentifierStr attribute", + it( + 'returns result of calling provided requestShortener"s shorten method ' + + "on readableIdentifierStr attribute", () => { const requestShortener = new RequestShortener(path.resolve()); should.exist(myRawModule.readableIdentifier(requestShortener)); @@ -45,17 +46,22 @@ describe("RawModule", () => { }); describe("source", () => { - it("returns a new OriginalSource instance with sourceStr attribute and " + - "return value of identifier() function provided as constructor arguments", + it( + "returns a new OriginalSource instance with sourceStr attribute and " + + "return value of identifier() function provided as constructor arguments", () => { - const originalSource = new OriginalSource(myRawModule.sourceStr, myRawModule.identifier()); + const originalSource = new OriginalSource( + myRawModule.sourceStr, + myRawModule.identifier() + ); myRawModule.useSourceMap = true; myRawModule.source().should.match(originalSource); } ); - it("returns a new RawSource instance with sourceStr attribute provided " + - "as constructor argument if useSourceMap is falsey", + it( + "returns a new RawSource instance with sourceStr attribute provided " + + "as constructor argument if useSourceMap is falsey", () => { const rawSource = new RawSource(myRawModule.sourceStr); myRawModule.useSourceMap = false; @@ -66,14 +72,14 @@ describe("RawModule", () => { describe("updateHash", () => { it("should include sourceStr in its hash", () => { - const hashModule = (module) => { + const hashModule = module => { const hash = crypto.createHash("sha256"); module.updateHash(hash); return hash.digest("hex"); }; - const hashFoo = hashModule(new RawModule("\"foo\"")); - const hashBar = hashModule(new RawModule("\"bar\"")); + const hashFoo = hashModule(new RawModule('"foo"')); + const hashBar = hashModule(new RawModule('"bar"')); hashFoo.should.not.equal(hashBar); }); }); diff --git a/test/RuleSet.unittest.js b/test/RuleSet.unittest.js index e456bbaa1..db49675a1 100644 --- a/test/RuleSet.unittest.js +++ b/test/RuleSet.unittest.js @@ -8,406 +8,471 @@ function match(ruleSet, resource) { const result = ruleSet.exec({ resource: resource }); - return result.filter((r) => { - return r.type === "use"; - }).map(r => r.value).map(r => { - if(!r.options) - return r.loader; - if(typeof r.options === "string") - return r.loader + "?" + r.options; - return r.loader + "?" + JSON.stringify(r.options); - }); + return result + .filter(r => { + return r.type === "use"; + }) + .map(r => r.value) + .map(r => { + if (!r.options) return r.loader; + if (typeof r.options === "string") return r.loader + "?" + r.options; + return r.loader + "?" + JSON.stringify(r.options); + }); } describe("RuleSet", () => { it("should create RuleSet with a blank array", () => { const loader = new RuleSet([]); - (loader.rules).should.eql([]); + loader.rules.should.eql([]); }); it("should create RuleSet and match with empty array", () => { const loader = new RuleSet([]); - (match(loader, "something")).should.eql([]); + match(loader, "something").should.eql([]); }); it("should not match with loaders array", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css" - }]); - (match(loader, "something")).should.eql([]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css" + } + ]); + match(loader, "something").should.eql([]); }); it("should match with regex", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should match with string", () => { - const loader = new RuleSet([{ - test: "style.css", - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: "style.css", + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should match with function", () => { - const loader = new RuleSet([{ - test: function(str) { - return str === "style.css"; - }, - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: function(str) { + return str === "style.css"; + }, + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should throw if invalid test", () => { should.throws(() => { - const loader = new RuleSet([{ - test: { - invalid: "test" - }, - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: { + invalid: "test" + }, + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }, /Unexcepted property invalid in condition/); }); it("should accept multiple test array that all match", () => { - const loader = new RuleSet([{ - test: [ - /style.css/, - /yle.css/ - ], - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: [/style.css/, /yle.css/], + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should accept multiple test array that not all match", () => { - const loader = new RuleSet([{ - test: [ - /style.css/, - /something.css/ - ], - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: [/style.css/, /something.css/], + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should not match if include does not match", () => { - const loader = new RuleSet([{ - test: /\.css$/, - include: /output.css/, - loader: "css" - }]); - (match(loader, "style.css")).should.eql([]); + const loader = new RuleSet([ + { + test: /\.css$/, + include: /output.css/, + loader: "css" + } + ]); + match(loader, "style.css").should.eql([]); }); it("should match if include matches", () => { - const loader = new RuleSet([{ - test: /\.css$/, - include: /style.css/, - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + include: /style.css/, + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should not match if exclude matches", () => { - const loader = new RuleSet([{ - test: /\.css$/, - exclude: /style.css/, - loader: "css" - }]); - (match(loader, "style.css")).should.eql([]); + const loader = new RuleSet([ + { + test: /\.css$/, + exclude: /style.css/, + loader: "css" + } + ]); + match(loader, "style.css").should.eql([]); }); it("should match if exclude does not match", () => { - const loader = new RuleSet([{ - test: /\.css$/, - exclude: /output.css/, - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + exclude: /output.css/, + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should work if a loader is applied to all files", () => { - const loader = new RuleSet([{ - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); - (match(loader, "scripts.js")).should.eql(["css"]); + const loader = new RuleSet([ + { + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); + match(loader, "scripts.js").should.eql(["css"]); }); it("should work with using loader as string", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should work with using loader as array", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: ["css"] - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: ["css"] + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should work with using loaders as string", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: "css" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: "css" + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should work with using loaders as array", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: ["css"] - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: ["css"] + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should throw if using loaders with non-string or array", () => { should.throws(function() { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: { - someObj: true + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: { + someObj: true + } } - }]); - (match(loader, "style.css")).should.eql(["css"]); + ]); + match(loader, "style.css").should.eql(["css"]); }, /No loader specified/); }); it("should work with using loader with inline query", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css?modules=1" - }]); - (match(loader, "style.css")).should.eql(["css?modules=1"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css?modules=1" + } + ]); + match(loader, "style.css").should.eql(["css?modules=1"]); }); it("should work with using loader with string query", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css", - query: "modules=1" - }]); - (match(loader, "style.css")).should.eql(["css?modules=1"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css", + query: "modules=1" + } + ]); + match(loader, "style.css").should.eql(["css?modules=1"]); }); it("should work with using loader with object query", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css", - query: { - modules: 1 + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css", + query: { + modules: 1 + } } - }]); - (match(loader, "style.css")).should.eql(["css?{\"modules\":1}"]); + ]); + match(loader, "style.css").should.eql(['css?{"modules":1}']); }); it("should work with using array loaders with basic object notation", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: [{ - loader: "css" - }] - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: [ + { + loader: "css" + } + ] + } + ]); + match(loader, "style.css").should.eql(["css"]); }); it("should throw if using array loaders with object notation without specifying a loader", () => { should.throws(() => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: [{ - stuff: 1 - }] - }]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: [ + { + stuff: 1 + } + ] + } + ]); match(loader, "style.css"); }, /No loader specified/); }); it("should work with using array loaders with object notation", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: [{ - loader: "css", - query: "modules=1" - }] - }]); - (match(loader, "style.css")).should.eql(["css?modules=1"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: [ + { + loader: "css", + query: "modules=1" + } + ] + } + ]); + match(loader, "style.css").should.eql(["css?modules=1"]); }); it("should work with using multiple array loaders with object notation", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: [{ - loader: "style", - query: "filesize=1000" - }, { - loader: "css", - query: "modules=1" - }] - }]); - (match(loader, "style.css")).should.eql(["style?filesize=1000", "css?modules=1"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: [ + { + loader: "style", + query: "filesize=1000" + }, + { + loader: "css", + query: "modules=1" + } + ] + } + ]); + match(loader, "style.css").should.eql([ + "style?filesize=1000", + "css?modules=1" + ]); }); it("should work with using string multiple loaders", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: "style?filesize=1000!css?modules=1" - }]); - (match(loader, "style.css")).should.eql(["style?filesize=1000", "css?modules=1"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: "style?filesize=1000!css?modules=1" + } + ]); + match(loader, "style.css").should.eql([ + "style?filesize=1000", + "css?modules=1" + ]); }); it("should throw if using array loaders with a single legacy", () => { should.throws(() => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: ["style-loader", "css-loader"], - query: "modules=1" - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: ["style-loader", "css-loader"], + query: "modules=1" + } + ]); + match(loader, "style.css").should.eql(["css"]); }, /options\/query cannot be used with loaders/); }); it("should work when using array loaders", () => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: ["style-loader", "css-loader"] - }]); - (match(loader, "style.css")).should.eql(["style-loader", "css-loader"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: ["style-loader", "css-loader"] + } + ]); + match(loader, "style.css").should.eql(["style-loader", "css-loader"]); }); it("should work when using an array of functions returning a loader", () => { - const loader = new RuleSet([{ - test: /\.css$/, - use: [ - function(data) { - return { - loader: "style-loader" - }; - }, - function(data) { - return { - loader: "css-loader" - }; - }, - ] - }]); - (match(loader, "style.css")).should.eql(["style-loader", "css-loader"]); + const loader = new RuleSet([ + { + test: /\.css$/, + use: [ + function(data) { + return { + loader: "style-loader" + }; + }, + function(data) { + return { + loader: "css-loader" + }; + } + ] + } + ]); + match(loader, "style.css").should.eql(["style-loader", "css-loader"]); }); it("should work when using an array of either functions or strings returning a loader", () => { - const loader = new RuleSet([{ - test: /\.css$/, - use: [ - "style-loader", - function(data) { - return { - loader: "css-loader" - }; - }, - ] - }]); - (match(loader, "style.css")).should.eql(["style-loader", "css-loader"]); + const loader = new RuleSet([ + { + test: /\.css$/, + use: [ + "style-loader", + function(data) { + return { + loader: "css-loader" + }; + } + ] + } + ]); + match(loader, "style.css").should.eql(["style-loader", "css-loader"]); }); it("should work when using an array of functions returning either a loader obejct or loader name string", () => { - const loader = new RuleSet([{ - test: /\.css$/, - use: [ - function(data) { - return "style-loader"; - }, - function(data) { - return { - loader: "css-loader" - }; - }, - ] - }]); - (match(loader, "style.css")).should.eql(["style-loader", "css-loader"]); + const loader = new RuleSet([ + { + test: /\.css$/, + use: [ + function(data) { + return "style-loader"; + }, + function(data) { + return { + loader: "css-loader" + }; + } + ] + } + ]); + match(loader, "style.css").should.eql(["style-loader", "css-loader"]); }); it("should throw if using array loaders with invalid type", () => { should.throws(() => { - const loader = new RuleSet([{ - test: /\.css$/, - loaders: ["style-loader", "css-loader", 5], - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loaders: ["style-loader", "css-loader", 5] + } + ]); + match(loader, "style.css").should.eql(["css"]); }, /No loader specified/); }); describe("when exclude array holds an undefined item", () => { function errorHasContext(err) { - if(/Expected condition but got falsy value/.test(err) && + if ( + /Expected condition but got falsy value/.test(err) && /test/.test(err) && /include/.test(err) && /exclude/.test(err) && /node_modules/.test(err) && - /undefined/.test(err)) { + /undefined/.test(err) + ) { return true; } } it("should throw with context", () => { should.throws(() => { - const loader = new RuleSet([{ - test: /\.css$/, - loader: "css", - include: [ - "src", - ], - exclude: [ - "node_modules", - undefined, - ], - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + test: /\.css$/, + loader: "css", + include: ["src"], + exclude: ["node_modules", undefined] + } + ]); + match(loader, "style.css").should.eql(["css"]); }, errorHasContext); }); it("in resource should throw with context", () => { should.throws(() => { - const loader = new RuleSet([{ - resource: { - test: /\.css$/, - include: [ - "src", - ], - exclude: [ - "node_modules", - undefined, - ], - }, - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + resource: { + test: /\.css$/, + include: ["src"], + exclude: ["node_modules", undefined] + } + } + ]); + match(loader, "style.css").should.eql(["css"]); }, errorHasContext); }); it("in issuer should throw with context", () => { should.throws(() => { - const loader = new RuleSet([{ - issuer: { - test: /\.css$/, - include: [ - "src", - ], - exclude: [ - "node_modules", - undefined, - ], - }, - }]); - (match(loader, "style.css")).should.eql(["css"]); + const loader = new RuleSet([ + { + issuer: { + test: /\.css$/, + include: ["src"], + exclude: ["node_modules", undefined] + } + } + ]); + match(loader, "style.css").should.eql(["css"]); }, errorHasContext); }); }); diff --git a/test/Schemas.lint.js b/test/Schemas.lint.js index 524af2be0..13b053488 100644 --- a/test/Schemas.lint.js +++ b/test/Schemas.lint.js @@ -20,18 +20,19 @@ describe("Schemas", () => { try { fileContent = fs.readFileSync(path.resolve(rootDir, filename), "utf-8"); content = JSON.parse(fileContent); - } catch(e) { + } catch (e) { errorWhileParsing = e; } it("should be parse-able", () => { - if(errorWhileParsing) throw errorWhileParsing; + if (errorWhileParsing) throw errorWhileParsing; }); - if(content) { - + if (content) { it("should be formated correctly", () => { - fileContent.replace(/\r\n?/g, "\n").should.be.eql(JSON.stringify(content, 0, 2) + "\n"); + fileContent + .replace(/\r\n?/g, "\n") + .should.be.eql(JSON.stringify(content, 0, 2) + "\n"); }); const arrayProperties = ["oneOf", "anyOf", "allOf"]; @@ -67,45 +68,57 @@ describe("Schemas", () => { const walker = item => { it("should only use allowed schema properties", () => { - const otherProperties = Object.keys(item).filter(p => allowedProperties.indexOf(p) < 0); - if(otherProperties.length > 0) { - throw new Error(`The properties ${otherProperties.join(", ")} are not allowed to use`); + const otherProperties = Object.keys(item).filter( + p => allowedProperties.indexOf(p) < 0 + ); + if (otherProperties.length > 0) { + throw new Error( + `The properties ${otherProperties.join( + ", " + )} are not allowed to use` + ); // When allowing more properties make sure to add nice error messages for them in WebpackOptionsValidationError } }); - if(Object.keys(item).indexOf("$ref") >= 0) { + if (Object.keys(item).indexOf("$ref") >= 0) { it("should not have other properties next to $ref", () => { - const otherProperties = Object.keys(item).filter(p => p !== "$ref"); - if(otherProperties.length > 0) { - throw new Error(`When using $ref not other properties are possible (${otherProperties.join(", ")})`); + const otherProperties = Object.keys(item).filter( + p => p !== "$ref" + ); + if (otherProperties.length > 0) { + throw new Error( + `When using $ref not other properties are possible (${otherProperties.join( + ", " + )})` + ); } }); } arrayProperties.forEach(prop => { - if(prop in item) { + if (prop in item) { describe(prop, () => { item[prop].forEach(walker); }); } }); - if("items" in item) { + if ("items" in item) { describe("items", () => { - if(Object.keys(item).join() !== "$ref") { + if (Object.keys(item).join() !== "$ref") { validateProperty(item.items); } walker(item.items); }); } - if("definitions" in item) { + if ("definitions" in item) { Object.keys(item.definitions).forEach(name => { describe(`#${name}`, () => { walker(item.definitions[name]); }); }); } - if("properties" in item) { + if ("properties" in item) { it("should have additionalProperties set to some value when descriping properties", () => { item.should.be.property("additionalProperties"); }); @@ -117,7 +130,7 @@ describe("Schemas", () => { }); }); } - if(typeof item.additionalProperties === "object") { + if (typeof item.additionalProperties === "object") { describe("properties", () => { validateProperty(item.additionalProperties); walker(item.additionalProperties); diff --git a/test/SideEffectsFlagPlugin.unittest.js b/test/SideEffectsFlagPlugin.unittest.js index be93f188c..3b4a7e291 100644 --- a/test/SideEffectsFlagPlugin.unittest.js +++ b/test/SideEffectsFlagPlugin.unittest.js @@ -4,40 +4,100 @@ const SideEffectsFlagPlugin = require("../lib/optimize/SideEffectsFlagPlugin"); describe("SideEffectsFlagPlugin", () => { it("should assume true", () => { - SideEffectsFlagPlugin.moduleHasSideEffects("./foo/bar.js", undefined).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./foo/bar.js", + undefined + ).should.eql(true); }); it("should understand boolean values", () => { - SideEffectsFlagPlugin.moduleHasSideEffects("./foo/bar.js", true).should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./foo/bar.js", false).should.eql(false); + SideEffectsFlagPlugin.moduleHasSideEffects("./foo/bar.js", true).should.eql( + true + ); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./foo/bar.js", + false + ).should.eql(false); }); it("should understand a glob", () => { - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "./src/**/*.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./x.js", "./src/**/*.js").should.eql(false); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "./**/src/x/y/z.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "**.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "./src/**/z.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "./**/x/**/z.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "./**/src/**").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "./**/src/*").should.eql(false); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "*.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "x/**/z.js").should.eql(false); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "src/**/z.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "src/**/{x,y,z}.js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "src/**/[x-z].js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "src/**/[[:lower:]].js").should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "!*.js").should.eql(false); - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", "!**/*.js").should.eql(false); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "./src/**/*.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./x.js", + "./src/**/*.js" + ).should.eql(false); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "./**/src/x/y/z.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "**.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "./src/**/z.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "./**/x/**/z.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "./**/src/**" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "./**/src/*" + ).should.eql(false); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "*.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "x/**/z.js" + ).should.eql(false); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "src/**/z.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "src/**/{x,y,z}.js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "src/**/[x-z].js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "src/**/[[:lower:]].js" + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "!*.js" + ).should.eql(false); + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + "!**/*.js" + ).should.eql(false); }); it("should understand arrays", () => { - const array = [ - "./src/**/*.js", - "./dirty.js", - ]; - SideEffectsFlagPlugin.moduleHasSideEffects("./src/x/y/z.js", array).should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./dirty.js", array).should.eql(true); - SideEffectsFlagPlugin.moduleHasSideEffects("./clean.js", array).should.eql(false); + const array = ["./src/**/*.js", "./dirty.js"]; + SideEffectsFlagPlugin.moduleHasSideEffects( + "./src/x/y/z.js", + array + ).should.eql(true); + SideEffectsFlagPlugin.moduleHasSideEffects("./dirty.js", array).should.eql( + true + ); + SideEffectsFlagPlugin.moduleHasSideEffects("./clean.js", array).should.eql( + false + ); }); }); diff --git a/test/SizeFormatHelpers.unittest.js b/test/SizeFormatHelpers.unittest.js index 988a02624..7d3f8c842 100644 --- a/test/SizeFormatHelpers.unittest.js +++ b/test/SizeFormatHelpers.unittest.js @@ -27,15 +27,21 @@ describe("SizeFormatHelpers", () => { }); it("should handle float mebibytes", () => { - should(SizeFormatHelpers.formatSize(12.5 * 1024 * 1024)).be.eql("12.5 MiB"); + should(SizeFormatHelpers.formatSize(12.5 * 1024 * 1024)).be.eql( + "12.5 MiB" + ); }); it("should handle integer gibibytes", () => { - should(SizeFormatHelpers.formatSize(3 * 1024 * 1024 * 1024)).be.eql("3 GiB"); + should(SizeFormatHelpers.formatSize(3 * 1024 * 1024 * 1024)).be.eql( + "3 GiB" + ); }); it("should handle float gibibytes", () => { - should(SizeFormatHelpers.formatSize(1.2 * 1024 * 1024 * 1024)).be.eql("1.2 GiB"); + should(SizeFormatHelpers.formatSize(1.2 * 1024 * 1024 * 1024)).be.eql( + "1.2 GiB" + ); }); }); }); diff --git a/test/SourceMapDevToolModuleOptionsPlugin.unittest.js b/test/SourceMapDevToolModuleOptionsPlugin.unittest.js index 0fb476589..9b3d0e0fb 100644 --- a/test/SourceMapDevToolModuleOptionsPlugin.unittest.js +++ b/test/SourceMapDevToolModuleOptionsPlugin.unittest.js @@ -8,26 +8,38 @@ describe("SourceMapDevToolModuleOptionsPlugin", () => { describe("when applied", () => { let eventBindings; - beforeEach(() => eventBindings = undefined); + beforeEach(() => (eventBindings = undefined)); describe("with module false and line-to-line false", () => { - beforeEach(() => - eventBindings = applyPluginWithOptions(SourceMapDevToolModuleOptionsPlugin, { - module: false, - lineToLine: false - })); + beforeEach( + () => + (eventBindings = applyPluginWithOptions( + SourceMapDevToolModuleOptionsPlugin, + { + module: false, + lineToLine: false + } + )) + ); - it("does not bind any event handlers", () => eventBindings.length.should.be.exactly(0)); + it("does not bind any event handlers", () => + eventBindings.length.should.be.exactly(0)); }); describe("with module true", () => { - beforeEach(() => - eventBindings = applyPluginWithOptions(SourceMapDevToolModuleOptionsPlugin, { - module: true, - lineToLine: false - })); + beforeEach( + () => + (eventBindings = applyPluginWithOptions( + SourceMapDevToolModuleOptionsPlugin, + { + module: true, + lineToLine: false + } + )) + ); - it("binds one event handler", () => eventBindings.length.should.be.exactly(1)); + it("binds one event handler", () => + eventBindings.length.should.be.exactly(1)); describe("event handler", () => { it("binds to build-module event", () => @@ -44,16 +56,23 @@ describe("SourceMapDevToolModuleOptionsPlugin", () => { }); describe("with line-to-line true", () => { - beforeEach(() => - eventBindings = applyPluginWithOptions(SourceMapDevToolModuleOptionsPlugin, { - module: false, - lineToLine: true - })); + beforeEach( + () => + (eventBindings = applyPluginWithOptions( + SourceMapDevToolModuleOptionsPlugin, + { + module: false, + lineToLine: true + } + )) + ); - it("binds one event handler", () => eventBindings.length.should.be.exactly(1)); + it("binds one event handler", () => + eventBindings.length.should.be.exactly(1)); describe("event handler", () => { - it("binds to build-module event", () => eventBindings[0].name.should.be.exactly("build-module")); + it("binds to build-module event", () => + eventBindings[0].name.should.be.exactly("build-module")); it("sets line-to-line flag", () => { const module = {}; @@ -66,16 +85,23 @@ describe("SourceMapDevToolModuleOptionsPlugin", () => { }); describe("with line-to-line object", () => { - beforeEach(() => - eventBindings = applyPluginWithOptions(SourceMapDevToolModuleOptionsPlugin, { - module: false, - lineToLine: {} - })); + beforeEach( + () => + (eventBindings = applyPluginWithOptions( + SourceMapDevToolModuleOptionsPlugin, + { + module: false, + lineToLine: {} + } + )) + ); - it("binds one event handler", () => eventBindings.length.should.be.exactly(1)); + it("binds one event handler", () => + eventBindings.length.should.be.exactly(1)); describe("event handler", () => { - it("binds to build-module event", () => eventBindings[0].name.should.be.exactly("build-module")); + it("binds to build-module event", () => + eventBindings[0].name.should.be.exactly("build-module")); describe("when module has no resource", () => { it("makes no changes", () => { diff --git a/test/Stats.test.js b/test/Stats.test.js index 93bf1f1d1..d59bc1965 100644 --- a/test/Stats.test.js +++ b/test/Stats.test.js @@ -14,33 +14,35 @@ describe("Stats", () => { }); compiler.outputFileSystem = new MemoryFs(); compiler.run((err, stats) => { - if(err) return done(err); + if (err) return done(err); try { - stats.toString({ - all: false, - env: true, - _env: "production" - }).should.be.eql( - "Environment (--env): \"production\"" - ); - stats.toString({ - all: false, - env: true, - _env: { - prod: ["foo", "bar"], - baz: true - } - }).should.be.eql( - "Environment (--env): {\n" + - " \"prod\": [\n" + - " \"foo\",\n" + - " \"bar\"\n" + - " ],\n" + - " \"baz\": true\n" + - "}" - ); + stats + .toString({ + all: false, + env: true, + _env: "production" + }) + .should.be.eql('Environment (--env): "production"'); + stats + .toString({ + all: false, + env: true, + _env: { + prod: ["foo", "bar"], + baz: true + } + }) + .should.be.eql( + "Environment (--env): {\n" + + ' "prod": [\n' + + ' "foo",\n' + + ' "bar"\n' + + " ],\n" + + ' "baz": true\n' + + "}" + ); done(); - } catch(e) { + } catch (e) { done(e); } }); diff --git a/test/Stats.unittest.js b/test/Stats.unittest.js index 065ffa318..5798741e7 100644 --- a/test/Stats.unittest.js +++ b/test/Stats.unittest.js @@ -6,175 +6,185 @@ require("should"); const Stats = require("../lib/Stats"); const packageJson = require("../package.json"); -describe("Stats", () => { - describe("Error Handling", () => { - describe("does have", () => { - it("hasErrors", () => { +describe( + "Stats", + () => { + describe("Error Handling", () => { + describe("does have", () => { + it("hasErrors", () => { + const mockStats = new Stats({ + children: [], + errors: ["firstError"], + hash: "1234", + compiler: { + context: "" + } + }); + mockStats.hasErrors().should.be.ok(); + }); + it("hasWarnings", () => { + const mockStats = new Stats({ + children: [], + warnings: ["firstError"], + hash: "1234", + compiler: { + context: "" + } + }); + mockStats.hasWarnings().should.be.ok(); + }); + }); + describe("does not have", () => { + it("hasErrors", () => { + const mockStats = new Stats({ + children: [], + errors: [], + hash: "1234", + compiler: { + context: "" + } + }); + mockStats.hasErrors().should.not.be.ok(); + }); + it("hasWarnings", () => { + const mockStats = new Stats({ + children: [], + warnings: [], + hash: "1234", + compiler: { + context: "" + } + }); + mockStats.hasWarnings().should.not.be.ok(); + }); + }); + describe("children have", () => { + it("hasErrors", () => { + const mockStats = new Stats({ + children: [ + { + getStats: () => + new Stats({ + errors: ["firstError"], + hash: "5678" + }) + } + ], + errors: [], + hash: "1234" + }); + mockStats.hasErrors().should.be.ok(); + }); + it("hasWarnings", () => { + const mockStats = new Stats({ + children: [ + { + getStats: () => + new Stats({ + warnings: ["firstError"], + hash: "5678" + }) + } + ], + warnings: [], + hash: "1234" + }); + mockStats.hasWarnings().should.be.ok(); + }); + }); + it("formatError handles string errors", () => { const mockStats = new Stats({ - children: [], errors: ["firstError"], - hash: "1234", - compiler: { - context: "" - } - }); - mockStats.hasErrors().should.be.ok(); - }); - it("hasWarnings", () => { - const mockStats = new Stats({ + warnings: [], + assets: [], + entrypoints: new Map(), + chunks: [], + modules: [], children: [], - warnings: ["firstError"], hash: "1234", + mainTemplate: { + outputOptions: { + path: "" + }, + getPublicPath: () => "path" + }, compiler: { context: "" } }); - mockStats.hasWarnings().should.be.ok(); + const obj = mockStats.toJson(); + obj.errors[0].should.be.equal("firstError"); }); }); - describe("does not have", () => { - it("hasErrors", () => { + describe("toJson", () => { + it("returns plain object representation", () => { const mockStats = new Stats({ + errors: [], + warnings: [], + assets: [], + entrypoints: new Map(), + chunks: [], + modules: [], children: [], + hash: "1234", + mainTemplate: { + outputOptions: { + path: "/" + }, + getPublicPath: () => "path" + }, + compiler: { + context: "" + } + }); + const result = mockStats.toJson(); + result.should.deepEqual({ + assets: [], + assetsByChunkName: {}, + children: [], + chunks: [], + entrypoints: {}, + filteredAssets: 0, + filteredModules: 0, errors: [], hash: "1234", - compiler: { - context: "" - } + modules: [], + outputPath: "/", + publicPath: "path", + version: packageJson.version, + warnings: [] }); - mockStats.hasErrors().should.not.be.ok(); - }); - it("hasWarnings", () => { - const mockStats = new Stats({ - children: [], - warnings: [], - hash: "1234", - compiler: { - context: "" - } - }); - mockStats.hasWarnings().should.not.be.ok(); }); }); - describe("children have", () => { - it("hasErrors", () => { - const mockStats = new Stats({ - children: [{ - getStats: () => new Stats({ - errors: ["firstError"], - hash: "5678" - }), - }], - errors: [], - hash: "1234" + describe("Presets", () => { + describe("presetToOptions", () => { + it("returns correct object with 'Normal'", () => { + Stats.presetToOptions("Normal").should.eql({}); }); - mockStats.hasErrors().should.be.ok(); - }); - it("hasWarnings", () => { - const mockStats = new Stats({ - children: [{ - getStats: () => new Stats({ - warnings: ["firstError"], - hash: "5678" - }), - }], - warnings: [], - hash: "1234" - }); - mockStats.hasWarnings().should.be.ok(); - }); - }); - it("formatError handles string errors", () => { - const mockStats = new Stats({ - errors: ["firstError"], - warnings: [], - assets: [], - entrypoints: new Map(), - chunks: [], - modules: [], - children: [], - hash: "1234", - mainTemplate: { - outputOptions: { - path: "" - }, - getPublicPath: () => "path" - }, - compiler: { - context: "" - } - }); - const obj = mockStats.toJson(); - obj.errors[0].should.be.equal("firstError"); - }); - }); - describe("toJson", () => { - it("returns plain object representation", () => { - const mockStats = new Stats({ - errors: [], - warnings: [], - assets: [], - entrypoints: new Map(), - chunks: [], - modules: [], - children: [], - hash: "1234", - mainTemplate: { - outputOptions: { - path: "/" - }, - getPublicPath: () => "path" - }, - compiler: { - context: "" - } - }); - const result = mockStats.toJson(); - result.should.deepEqual({ - assets: [], - assetsByChunkName: {}, - children: [], - chunks: [], - entrypoints: {}, - filteredAssets: 0, - filteredModules: 0, - errors: [], - hash: "1234", - modules: [], - outputPath: "/", - publicPath: "path", - version: packageJson.version, - warnings: [] - }); - }); - }); - describe("Presets", () => { - describe("presetToOptions", () => { - it("returns correct object with 'Normal'", () => { - Stats.presetToOptions("Normal").should.eql({}); - }); - it("truthy values behave as 'normal'", () => { - const normalOpts = Stats.presetToOptions("normal"); - Stats.presetToOptions("pizza").should.eql(normalOpts); - Stats.presetToOptions(true).should.eql(normalOpts); - Stats.presetToOptions(1).should.eql(normalOpts); + it("truthy values behave as 'normal'", () => { + const normalOpts = Stats.presetToOptions("normal"); + Stats.presetToOptions("pizza").should.eql(normalOpts); + Stats.presetToOptions(true).should.eql(normalOpts); + Stats.presetToOptions(1).should.eql(normalOpts); - Stats.presetToOptions("verbose").should.not.eql(normalOpts); - Stats.presetToOptions(false).should.not.eql(normalOpts); - }); - it("returns correct object with 'none'", () => { - Stats.presetToOptions("none").should.eql({ - all: false + Stats.presetToOptions("verbose").should.not.eql(normalOpts); + Stats.presetToOptions(false).should.not.eql(normalOpts); + }); + it("returns correct object with 'none'", () => { + Stats.presetToOptions("none").should.eql({ + all: false + }); + }); + it("falsy values behave as 'none'", () => { + const noneOpts = Stats.presetToOptions("none"); + Stats.presetToOptions("").should.eql(noneOpts); + Stats.presetToOptions(null).should.eql(noneOpts); + Stats.presetToOptions().should.eql(noneOpts); + Stats.presetToOptions(0).should.eql(noneOpts); + Stats.presetToOptions(false).should.eql(noneOpts); }); }); - it("falsy values behave as 'none'", () => { - const noneOpts = Stats.presetToOptions("none"); - Stats.presetToOptions("").should.eql(noneOpts); - Stats.presetToOptions(null).should.eql(noneOpts); - Stats.presetToOptions().should.eql(noneOpts); - Stats.presetToOptions(0).should.eql(noneOpts); - Stats.presetToOptions(false).should.eql(noneOpts); - }); }); - }); -}, 10000); + }, + 10000 +); diff --git a/test/StatsTestCases.test.js b/test/StatsTestCases.test.js index 05da606c6..e75a40383 100644 --- a/test/StatsTestCases.test.js +++ b/test/StatsTestCases.test.js @@ -10,10 +10,13 @@ const Stats = require("../lib/Stats"); const base = path.join(__dirname, "statsCases"); const outputBase = path.join(__dirname, "js", "stats"); -const tests = fs.readdirSync(base).filter(testName => - fs.existsSync(path.join(base, testName, "index.js")) || - fs.existsSync(path.join(base, testName, "webpack.config.js")) -); +const tests = fs + .readdirSync(base) + .filter( + testName => + fs.existsSync(path.join(base, testName, "index.js")) || + fs.existsSync(path.join(base, testName, "webpack.config.js")) + ); describe("StatsTestCases", () => { tests.forEach(testName => { @@ -26,43 +29,52 @@ describe("StatsTestCases", () => { filename: "bundle.js" } }; - if(fs.existsSync(path.join(base, testName, "webpack.config.js"))) { + if (fs.existsSync(path.join(base, testName, "webpack.config.js"))) { options = require(path.join(base, testName, "webpack.config.js")); } - (Array.isArray(options) ? options : [options]).forEach((options) => { - if(!options.context) options.context = path.join(base, testName); - if(!options.output) options.output = options.output || {}; - if(!options.output.path) options.output.path = path.join(outputBase, testName); - if(!options.plugins) options.plugins = []; - if(!options.optimization) options.optimization = {}; - if(options.optimization.minimize === undefined) options.optimization.minimize = false; + (Array.isArray(options) ? options : [options]).forEach(options => { + if (!options.context) options.context = path.join(base, testName); + if (!options.output) options.output = options.output || {}; + if (!options.output.path) + options.output.path = path.join(outputBase, testName); + if (!options.plugins) options.plugins = []; + if (!options.optimization) options.optimization = {}; + if (options.optimization.minimize === undefined) + options.optimization.minimize = false; // To support deprecated loaders // TODO remove in webpack 5 - options.plugins.push(new webpack.LoaderOptionsPlugin({ - options: {} - })); + options.plugins.push( + new webpack.LoaderOptionsPlugin({ + options: {} + }) + ); }); const c = webpack(options); const compilers = c.compilers ? c.compilers : [c]; - compilers.forEach((c) => { + compilers.forEach(c => { const ifs = c.inputFileSystem; c.inputFileSystem = Object.create(ifs); c.inputFileSystem.readFile = function() { const args = Array.prototype.slice.call(arguments); const callback = args.pop(); - ifs.readFile.apply(ifs, args.concat([(err, result) => { - if(err) return callback(err); - callback(null, result.toString("utf-8").replace(/\r/g, "")); - }])); + ifs.readFile.apply( + ifs, + args.concat([ + (err, result) => { + if (err) return callback(err); + callback(null, result.toString("utf-8").replace(/\r/g, "")); + } + ]) + ); }; new webpack.optimize.OccurrenceOrderPlugin().apply(c); }); c.run((err, stats) => { - if(err) return done(err); + if (err) return done(err); - if(/error$/.test(testName)) { + if (/error$/.test(testName)) { stats.hasErrors().should.be.equal(true); - } else if(stats.hasErrors()) { + } else if (stats.hasErrors()) { return done(new Error(stats.toJson().errors.join("\n\n"))); } @@ -71,25 +83,29 @@ describe("StatsTestCases", () => { colors: false }; let hasColorSetting = false; - if(typeof options.stats !== "undefined") { + if (typeof options.stats !== "undefined") { toStringOptions = options.stats; - if(toStringOptions === null || typeof toStringOptions !== "object") + if (toStringOptions === null || typeof toStringOptions !== "object") toStringOptions = Stats.presetToOptions(toStringOptions); hasColorSetting = typeof options.stats.colors !== "undefined"; - if(!toStringOptions.context) toStringOptions.context = path.join(base, testName); + if (!toStringOptions.context) + toStringOptions.context = path.join(base, testName); } - if(Array.isArray(options) && !toStringOptions.children) { + if (Array.isArray(options) && !toStringOptions.children) { toStringOptions.children = options.map(o => o.stats); } let actual = stats.toString(toStringOptions); (typeof actual).should.be.eql("string"); - if(!hasColorSetting) { + if (!hasColorSetting) { actual = actual .replace(/\u001b\[[0-9;]*m/g, "") .replace(/[0-9]+(\s?ms)/g, "X$1") - .replace(/^(\s*Built at:) (.*)$/gm, "$1 Thu Jan 01 1970 00:00:00 GMT"); + .replace( + /^(\s*Built at:) (.*)$/gm, + "$1 Thu Jan 01 1970 00:00:00 GMT" + ); } else { actual = actual .replace(/\u001b\[1m\u001b\[([0-9;]*)m/g, "") @@ -97,7 +113,10 @@ describe("StatsTestCases", () => { .replace(/\u001b\[39m\u001b\[22m/g, "") .replace(/\u001b\[([0-9;]*)m/g, "") .replace(/[0-9]+(<\/CLR>)?(\s?ms)/g, "X$1$2") - .replace(/^(\s*Built at:) (.*)$/gm, "$1 Thu Jan 01 1970 00:00:00 GMT"); + .replace( + /^(\s*Built at:) (.*)$/gm, + "$1 Thu Jan 01 1970 00:00:00 GMT" + ); } actual = actual @@ -105,10 +124,16 @@ describe("StatsTestCases", () => { .replace(/[\t ]*Version:.+\n/g, "") .replace(path.join(base, testName), "Xdir/" + testName) .replace(/ dependencies:Xms/g, ""); - const expected = fs.readFileSync(path.join(base, testName, "expected.txt"), "utf-8").replace(/\r/g, ""); - if(actual !== expected) { - fs.writeFileSync(path.join(base, testName, "actual.txt"), actual, "utf-8"); - } else if(fs.existsSync(path.join(base, testName, "actual.txt"))) { + const expected = fs + .readFileSync(path.join(base, testName, "expected.txt"), "utf-8") + .replace(/\r/g, ""); + if (actual !== expected) { + fs.writeFileSync( + path.join(base, testName, "actual.txt"), + actual, + "utf-8" + ); + } else if (fs.existsSync(path.join(base, testName, "actual.txt"))) { fs.unlinkSync(path.join(base, testName, "actual.txt")); } actual.should.be.eql(expected); diff --git a/test/Template.unittest.js b/test/Template.unittest.js index 6a5a7c6a6..fd1dcc68e 100644 --- a/test/Template.unittest.js +++ b/test/Template.unittest.js @@ -10,11 +10,11 @@ describe("Template", () => { it("should generate valid number identifiers", () => { const items = []; let item; - for(let i = 0; i < 80; i += 1) { + for (let i = 0; i < 80; i += 1) { item = Template.numberToIdentifer(i); - if(item === "") { + if (item === "") { throw new Error("empty number identifier"); - } else if(items.indexOf(item) > -1) { + } else if (items.indexOf(item) > -1) { throw new Error("duplicate number identifier"); } else { items.push(item); @@ -22,6 +22,8 @@ describe("Template", () => { } }); it("should generate sanitized path identifiers", () => { - Template.toPath("path/to-sdfas/sadfome$$.js").should.equal("path-to-sdfas-sadfome$$-js"); + Template.toPath("path/to-sdfas/sadfome$$.js").should.equal( + "path-to-sdfas-sadfome$$-js" + ); }); }); diff --git a/test/TestCases.test.js b/test/TestCases.test.js index a74c3557e..dccfbae01 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -31,205 +31,307 @@ const DEFAULT_OPTIMIZATIONS = { noEmitOnErrors: false, concatenateModules: false, namedModules: false, - minimizer: [ - uglifyJsForTesting - ] + minimizer: [uglifyJsForTesting] }; const NO_EMIT_ON_ERRORS_OPTIMIZATIONS = { noEmitOnErrors: false, - minimizer: [ - uglifyJsForTesting - ] + minimizer: [uglifyJsForTesting] }; describe("TestCases", () => { const casesPath = path.join(__dirname, "cases"); let categories = fs.readdirSync(casesPath); - categories = categories.map((cat) => { + categories = categories.map(cat => { return { name: cat, - tests: fs.readdirSync(path.join(casesPath, cat)).filter((folder) => folder.indexOf("_") < 0) + tests: fs + .readdirSync(path.join(casesPath, cat)) + .filter(folder => folder.indexOf("_") < 0) }; }); - [{ - name: "normal", - }, { - name: "production", - mode: "production", - }, { - name: "development", - mode: "development", - devtool: "none" - }, { - name: "hot", - plugins: [ - new webpack.HotModuleReplacementPlugin() - ] - }, { - name: "hot-multi-step", - plugins: [ - new webpack.HotModuleReplacementPlugin({ - multiStep: true - }) - ] - }, { - name: "devtool-eval", - devtool: "eval" - }, { - name: "devtool-eval-named-modules", - devtool: "eval", - plugins: [ - new webpack.NamedModulesPlugin() - ] - }, { - name: "devtool-eval-source-map", - devtool: "#eval-source-map" - }, { - name: "devtool-inline-source-map", - devtool: "inline-source-map" - }, { - name: "devtool-source-map", - devtool: "#@source-map" - }, { - name: "devtool-cheap-inline-source-map", - devtool: "cheap-inline-source-map" - }, { - name: "devtool-cheap-eval-source-map", - devtool: "cheap-eval-source-map" - }, { - name: "devtool-cheap-eval-module-source-map", - devtool: "cheap-eval-module-source-map" - }, { - name: "devtool-cheap-source-map", - devtool: "cheap-source-map" - }, { - name: "minimized-source-map", - mode: "production", - devtool: "eval-cheap-module-source-map", - minimize: true - }, { - name: "minimized-hashed-modules", - mode: "production", - minimize: true, - plugins: [ - new webpack.HashedModuleIdsPlugin() - ] - }, { - name: "all-combined", - mode: "production", - devtool: "#@source-map", - minimize: true, - plugins: [ - new webpack.HotModuleReplacementPlugin(), - new webpack.NamedModulesPlugin(), - new webpack.NamedChunksPlugin() - ] - }].forEach((config) => { + [ + { + name: "normal" + }, + { + name: "production", + mode: "production" + }, + { + name: "development", + mode: "development", + devtool: "none" + }, + { + name: "hot", + plugins: [new webpack.HotModuleReplacementPlugin()] + }, + { + name: "hot-multi-step", + plugins: [ + new webpack.HotModuleReplacementPlugin({ + multiStep: true + }) + ] + }, + { + name: "devtool-eval", + devtool: "eval" + }, + { + name: "devtool-eval-named-modules", + devtool: "eval", + plugins: [new webpack.NamedModulesPlugin()] + }, + { + name: "devtool-eval-source-map", + devtool: "#eval-source-map" + }, + { + name: "devtool-inline-source-map", + devtool: "inline-source-map" + }, + { + name: "devtool-source-map", + devtool: "#@source-map" + }, + { + name: "devtool-cheap-inline-source-map", + devtool: "cheap-inline-source-map" + }, + { + name: "devtool-cheap-eval-source-map", + devtool: "cheap-eval-source-map" + }, + { + name: "devtool-cheap-eval-module-source-map", + devtool: "cheap-eval-module-source-map" + }, + { + name: "devtool-cheap-source-map", + devtool: "cheap-source-map" + }, + { + name: "minimized-source-map", + mode: "production", + devtool: "eval-cheap-module-source-map", + minimize: true + }, + { + name: "minimized-hashed-modules", + mode: "production", + minimize: true, + plugins: [new webpack.HashedModuleIdsPlugin()] + }, + { + name: "all-combined", + mode: "production", + devtool: "#@source-map", + minimize: true, + plugins: [ + new webpack.HotModuleReplacementPlugin(), + new webpack.NamedModulesPlugin(), + new webpack.NamedChunksPlugin() + ] + } + ].forEach(config => { describe(config.name, () => { - categories.forEach((category) => { + categories.forEach(category => { describe(category.name, function() { this.timeout(30000); - category.tests.filter((test) => { - const testDirectory = path.join(casesPath, category.name, test); - const filterPath = path.join(testDirectory, "test.filter.js"); - if(fs.existsSync(filterPath) && !require(filterPath)(config)) { - describe.skip(test, () => it("filtered")); - return false; - } - return true; - }).forEach((testName) => { - const suite = describe(testName, () => {}); - it(testName + " should compile", (done) => { - const testDirectory = path.join(casesPath, category.name, testName); - const outputDirectory = path.join(__dirname, "js", config.name, category.name, testName); - const options = { - context: casesPath, - entry: "./" + category.name + "/" + testName + "/index", - target: "async-node", - devtool: config.devtool, - mode: config.mode || "none", - optimization: config.mode ? NO_EMIT_ON_ERRORS_OPTIMIZATIONS : Object.assign({}, config.optimization, DEFAULT_OPTIMIZATIONS), - performance: { - hints: false - }, - output: { - pathinfo: true, - path: outputDirectory, - filename: "bundle.js" - }, - resolve: { - modules: ["web_modules", "node_modules"], - mainFields: ["webpack", "browser", "web", "browserify", ["jam", "main"], "main"], - aliasFields: ["browser"], - extensions: [".mjs", ".webpack.js", ".web.js", ".js", ".json"], - concord: true - }, - resolveLoader: { - modules: ["web_loaders", "web_modules", "node_loaders", "node_modules"], - mainFields: ["webpackLoader", "webLoader", "loader", "main"], - extensions: [".webpack-loader.js", ".web-loader.js", ".loader.js", ".js"] - }, - module: { - rules: [{ - test: /\.coffee$/, - loader: "coffee-loader" - }, { - test: /\.jade$/, - loader: "jade-loader" - }] - }, - plugins: (config.plugins || []).concat(function() { - this.hooks.compilation.tap("TestCasesTest", (compilation) => { - ["optimize", "optimizeModulesBasic", "optimizeChunksBasic", "afterOptimizeTree", "afterOptimizeAssets"].forEach((hook) => { - compilation.hooks[hook].tap("TestCasesTest", () => compilation.checkConstraints()); + category.tests + .filter(test => { + const testDirectory = path.join(casesPath, category.name, test); + const filterPath = path.join(testDirectory, "test.filter.js"); + if (fs.existsSync(filterPath) && !require(filterPath)(config)) { + describe.skip(test, () => it("filtered")); + return false; + } + return true; + }) + .forEach(testName => { + const suite = describe(testName, () => {}); + it(testName + " should compile", done => { + const testDirectory = path.join( + casesPath, + category.name, + testName + ); + const outputDirectory = path.join( + __dirname, + "js", + config.name, + category.name, + testName + ); + const options = { + context: casesPath, + entry: "./" + category.name + "/" + testName + "/index", + target: "async-node", + devtool: config.devtool, + mode: config.mode || "none", + optimization: config.mode + ? NO_EMIT_ON_ERRORS_OPTIMIZATIONS + : Object.assign( + {}, + config.optimization, + DEFAULT_OPTIMIZATIONS + ), + performance: { + hints: false + }, + output: { + pathinfo: true, + path: outputDirectory, + filename: "bundle.js" + }, + resolve: { + modules: ["web_modules", "node_modules"], + mainFields: [ + "webpack", + "browser", + "web", + "browserify", + ["jam", "main"], + "main" + ], + aliasFields: ["browser"], + extensions: [ + ".mjs", + ".webpack.js", + ".web.js", + ".js", + ".json" + ], + concord: true + }, + resolveLoader: { + modules: [ + "web_loaders", + "web_modules", + "node_loaders", + "node_modules" + ], + mainFields: [ + "webpackLoader", + "webLoader", + "loader", + "main" + ], + extensions: [ + ".webpack-loader.js", + ".web-loader.js", + ".loader.js", + ".js" + ] + }, + module: { + rules: [ + { + test: /\.coffee$/, + loader: "coffee-loader" + }, + { + test: /\.jade$/, + loader: "jade-loader" + } + ] + }, + plugins: (config.plugins || []).concat(function() { + this.hooks.compilation.tap("TestCasesTest", compilation => { + [ + "optimize", + "optimizeModulesBasic", + "optimizeChunksBasic", + "afterOptimizeTree", + "afterOptimizeAssets" + ].forEach(hook => { + compilation.hooks[hook].tap("TestCasesTest", () => + compilation.checkConstraints() + ); + }); }); + }) + }; + webpack(options, (err, stats) => { + if (err) return done(err); + const statOptions = Stats.presetToOptions("verbose"); + statOptions.colors = false; + mkdirp.sync(outputDirectory); + fs.writeFileSync( + path.join(outputDirectory, "stats.txt"), + stats.toString(statOptions), + "utf-8" + ); + const jsonStats = stats.toJson({ + errorDetails: true }); - }) - }; - webpack(options, (err, stats) => { - if(err) return done(err); - const statOptions = Stats.presetToOptions("verbose"); - statOptions.colors = false; - mkdirp.sync(outputDirectory); - fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8"); - const jsonStats = stats.toJson({ - errorDetails: true + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "error", + "Error", + done + ) + ) + return; + if ( + checkArrayExpectation( + testDirectory, + jsonStats, + "warning", + "Warning", + done + ) + ) + return; + let exportedTest = 0; + + function _it(title, fn) { + const test = new Test(title, fn); + suite.addTest(test); + exportedTest++; + // WORKAROUND for a v8 bug + // Error objects retrain all scopes in the stacktrace + test._trace = test._trace.message; + + return test; + } + + function _require(module) { + if (module.substr(0, 2) === "./") { + const p = path.join(outputDirectory, module); + const fn = vm.runInThisContext( + "(function(require, module, exports, __dirname, it) {" + + fs.readFileSync(p, "utf-8") + + "\n})", + p + ); + const m = { + exports: {}, + webpackTestSuiteModule: true + }; + fn.call( + m.exports, + _require, + m, + m.exports, + outputDirectory, + _it + ); + return m.exports; + } else return require(module); + } + _require.webpackTestSuiteRequire = true; + _require("./bundle.js"); + if (exportedTest === 0) + return done(new Error("No tests exported by test case")); + done(); }); - if(checkArrayExpectation(testDirectory, jsonStats, "error", "Error", done)) return; - if(checkArrayExpectation(testDirectory, jsonStats, "warning", "Warning", done)) return; - let exportedTest = 0; - - function _it(title, fn) { - const test = new Test(title, fn); - suite.addTest(test); - exportedTest++; - // WORKAROUND for a v8 bug - // Error objects retrain all scopes in the stacktrace - test._trace = test._trace.message; - - return test; - } - - function _require(module) { - if(module.substr(0, 2) === "./") { - const p = path.join(outputDirectory, module); - const fn = vm.runInThisContext("(function(require, module, exports, __dirname, it) {" + fs.readFileSync(p, "utf-8") + "\n})", p); - const m = { - exports: {}, - webpackTestSuiteModule: true - }; - fn.call(m.exports, _require, m, m.exports, outputDirectory, _it); - return m.exports; - } else return require(module); - } - _require.webpackTestSuiteRequire = true; - _require("./bundle.js"); - if(exportedTest === 0) return done(new Error("No tests exported by test case")); - done(); }); }); - }); }); }); }); diff --git a/test/Validation.test.js b/test/Validation.test.js index 123d3dd1b..ebc80462b 100644 --- a/test/Validation.test.js +++ b/test/Validation.test.js @@ -6,362 +6,384 @@ require("should"); const webpack = require("../lib/webpack"); describe("Validation", () => { - const testCases = [{ - name: "undefined configuration", - config: undefined, - message: [ - " - configuration should be an object." - ] - }, { - name: "null configuration", - config: null, - message: [ - " - configuration should be an object." - ] - }, { - name: "empty entry string", - config: { - entry: "" + const testCases = [ + { + name: "undefined configuration", + config: undefined, + message: [" - configuration should be an object."] }, - message: [ - " - configuration.entry should be one of these:", - " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", - " -> The entry point(s) of the compilation.", - " Details:", - " * configuration.entry should be an object.", - " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", - " * configuration.entry should not be empty.", - " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", - " * configuration.entry should be an array:", - " [non-empty string]", - " * configuration.entry should be an instance of function", - " -> A Function returning an entry object, an entry string, an entry array or a promise to these things." - ] - }, { - name: "empty entry bundle array", - config: { - entry: { - "bundle": [] - } + { + name: "null configuration", + config: null, + message: [" - configuration should be an object."] }, - message: [ - " - configuration.entry should be one of these:", - " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", - " -> The entry point(s) of the compilation.", - " Details:", - " * configuration.entry['bundle'] should be a string.", - " -> The string is resolved to a module which is loaded upon startup.", - " * configuration.entry['bundle'] should not be empty.", - " * configuration.entry should be a string.", - " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", - " * configuration.entry should be an array:", - " [non-empty string]", - " * configuration.entry should be an instance of function", - " -> A Function returning an entry object, an entry string, an entry array or a promise to these things." - ] - }, { - name: "invalid instanceof", - config: { - entry: "a", - module: { - wrappedContextRegExp: 1337 - } - }, - message: [ - " - configuration.module.wrappedContextRegExp should be an instance of RegExp", - " -> Set the inner regular expression for partial dynamic dependencies" - ] - }, { - name: "invalid minimum", - config: { - entry: "a", - parallelism: 0 - }, - message: [ - " - configuration.parallelism should be >= 1.", - " -> The number of parallel processed modules in the compilation." - ] - }, { - name: "repeated value", - config: { - entry: ["abc", "def", "abc"] - }, - message: [ - " - configuration.entry should be one of these:", - " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", - " -> The entry point(s) of the compilation.", - " Details:", - " * configuration.entry should be an object.", - " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", - " * configuration.entry should be a string.", - " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", - " * configuration.entry should not contain the item 'abc' twice.", - " * configuration.entry should be an instance of function", - " -> A Function returning an entry object, an entry string, an entry array or a promise to these things.", - ] - }, { - name: "multiple errors", - config: { - entry: [/a/], - output: { - filename: /a/ - } - }, - message: [ - " - configuration.entry should be one of these:", - " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", - " -> The entry point(s) of the compilation.", - " Details:", - " * configuration.entry should be an object.", - " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", - " * configuration.entry should be a string.", - " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", - " * configuration.entry[0] should be a string.", - " -> A non-empty string", - " * configuration.entry should be an instance of function", - " -> A Function returning an entry object, an entry string, an entry array or a promise to these things.", - " - configuration.output.filename should be one of these:", - " string | function", - " -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", - " Details:", - " * configuration.output.filename should be a string.", - " * configuration.output.filename should be an instance of function" - ] - }, { - name: "multiple configurations", - config: [{ - entry: [/a/], - }, { - entry: "a", - output: { - filename: /a/ - } - }], - message: [ - " - configuration[0].entry should be one of these:", - " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", - " -> The entry point(s) of the compilation.", - " Details:", - " * configuration[0].entry should be an object.", - " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", - " * configuration[0].entry should be a string.", - " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", - " * configuration[0].entry[0] should be a string.", - " -> A non-empty string", - " * configuration[0].entry should be an instance of function", - " -> A Function returning an entry object, an entry string, an entry array or a promise to these things.", - " - configuration[1].output.filename should be one of these:", - " string | function", - " -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", - " Details:", - " * configuration[1].output.filename should be a string.", - " * configuration[1].output.filename should be an instance of function", - ] - }, { - name: "deep error", - config: { - entry: "a", - module: { - rules: [{ - oneOf: [{ - test: "/a", - paser: { - amd: false - } - }] - }] - } - }, - message: [ - " - configuration.module.rules[0].oneOf[0] has an unknown property 'paser'. These properties are valid:", - " object { enforce?, exclude?, include?, issuer?, loader?, loaders?, oneOf?, options?, parser?, resolve?, sideEffects?, query?, type?, resource?, resourceQuery?, compiler?, rules?, test?, use? }", - " -> A rule" - ] - }, { - name: "additional key on root", - config: { - entry: "a", - postcss: () => {} - }, - message: [ - " - configuration has an unknown property 'postcss'. These properties are valid:", - " object { mode?, amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, externals?, " + - "loader?, module?, name?, node?, output?, optimization?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, " + - "recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, stats?, target?, watch?, watchOptions? }", - " For typos: please correct them.", - " For loader options: webpack 2 no longer allows custom properties in configuration.", - " Loaders should be updated to allow passing options via loader options in module.rules.", - " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:", - " plugins: [", - " new webpack.LoaderOptionsPlugin({", - " // test: /\\.xxx$/, // may apply this only for some modules", - " options: {", - " postcss: ...", - " }", - " })", - " ]" - ] - }, { - name: "enum", - config: { - entry: "a", - devtool: true - }, - message: [ - " - configuration.devtool should be one of these:", - " string | false", - " -> A developer tool to enhance debugging.", - " Details:", - " * configuration.devtool should be a string.", - " * configuration.devtool should be false" - ] - }, { - name: "relative path", - config: { - entry: "foo.js", - output: { - filename: "/bar" - } - }, - message: [ - " - configuration.output.filename: A relative path is expected. However the provided value \"/bar\" is an absolute path!", - " -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", - " Please use output.path to specify absolute path and output.filename for the file name." - ] - }, { - name: "absolute path", - config: { - entry: "foo.js", - output: { - filename: "bar" + { + name: "empty entry string", + config: { + entry: "" }, - context: "baz" + message: [ + " - configuration.entry should be one of these:", + " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", + " -> The entry point(s) of the compilation.", + " Details:", + " * configuration.entry should be an object.", + " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", + " * configuration.entry should not be empty.", + " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", + " * configuration.entry should be an array:", + " [non-empty string]", + " * configuration.entry should be an instance of function", + " -> A Function returning an entry object, an entry string, an entry array or a promise to these things." + ] }, - message: [ - " - configuration.context: The provided value \"baz\" is not an absolute path!", - " -> The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory." - ] - }, { - name: "missing stats option", - config: { - entry: "foo.js", - stats: { - foobar: true + { + name: "empty entry bundle array", + config: { + entry: { + bundle: [] + } + }, + message: [ + " - configuration.entry should be one of these:", + " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", + " -> The entry point(s) of the compilation.", + " Details:", + " * configuration.entry['bundle'] should be a string.", + " -> The string is resolved to a module which is loaded upon startup.", + " * configuration.entry['bundle'] should not be empty.", + " * configuration.entry should be a string.", + " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", + " * configuration.entry should be an array:", + " [non-empty string]", + " * configuration.entry should be an instance of function", + " -> A Function returning an entry object, an entry string, an entry array or a promise to these things." + ] + }, + { + name: "invalid instanceof", + config: { + entry: "a", + module: { + wrappedContextRegExp: 1337 + } + }, + message: [ + " - configuration.module.wrappedContextRegExp should be an instance of RegExp", + " -> Set the inner regular expression for partial dynamic dependencies" + ] + }, + { + name: "invalid minimum", + config: { + entry: "a", + parallelism: 0 + }, + message: [ + " - configuration.parallelism should be >= 1.", + " -> The number of parallel processed modules in the compilation." + ] + }, + { + name: "repeated value", + config: { + entry: ["abc", "def", "abc"] + }, + message: [ + " - configuration.entry should be one of these:", + " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", + " -> The entry point(s) of the compilation.", + " Details:", + " * configuration.entry should be an object.", + " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", + " * configuration.entry should be a string.", + " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", + " * configuration.entry should not contain the item 'abc' twice.", + " * configuration.entry should be an instance of function", + " -> A Function returning an entry object, an entry string, an entry array or a promise to these things." + ] + }, + { + name: "multiple errors", + config: { + entry: [/a/], + output: { + filename: /a/ + } + }, + message: [ + " - configuration.entry should be one of these:", + " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", + " -> The entry point(s) of the compilation.", + " Details:", + " * configuration.entry should be an object.", + " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", + " * configuration.entry should be a string.", + " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", + " * configuration.entry[0] should be a string.", + " -> A non-empty string", + " * configuration.entry should be an instance of function", + " -> A Function returning an entry object, an entry string, an entry array or a promise to these things.", + " - configuration.output.filename should be one of these:", + " string | function", + " -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", + " Details:", + " * configuration.output.filename should be a string.", + " * configuration.output.filename should be an instance of function" + ] + }, + { + name: "multiple configurations", + config: [ + { + entry: [/a/] + }, + { + entry: "a", + output: { + filename: /a/ + } + } + ], + message: [ + " - configuration[0].entry should be one of these:", + " object { : non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function", + " -> The entry point(s) of the compilation.", + " Details:", + " * configuration[0].entry should be an object.", + " -> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", + " * configuration[0].entry should be a string.", + " -> An entry point without name. The string is resolved to a module which is loaded upon startup.", + " * configuration[0].entry[0] should be a string.", + " -> A non-empty string", + " * configuration[0].entry should be an instance of function", + " -> A Function returning an entry object, an entry string, an entry array or a promise to these things.", + " - configuration[1].output.filename should be one of these:", + " string | function", + " -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", + " Details:", + " * configuration[1].output.filename should be a string.", + " * configuration[1].output.filename should be an instance of function" + ] + }, + { + name: "deep error", + config: { + entry: "a", + module: { + rules: [ + { + oneOf: [ + { + test: "/a", + paser: { + amd: false + } + } + ] + } + ] + } + }, + message: [ + " - configuration.module.rules[0].oneOf[0] has an unknown property 'paser'. These properties are valid:", + " object { enforce?, exclude?, include?, issuer?, loader?, loaders?, oneOf?, options?, parser?, resolve?, sideEffects?, query?, type?, resource?, resourceQuery?, compiler?, rules?, test?, use? }", + " -> A rule" + ] + }, + { + name: "additional key on root", + config: { + entry: "a", + postcss: () => {} + }, + message: [ + " - configuration has an unknown property 'postcss'. These properties are valid:", + " object { mode?, amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, externals?, " + + "loader?, module?, name?, node?, output?, optimization?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, " + + "recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, stats?, target?, watch?, watchOptions? }", + " For typos: please correct them.", + " For loader options: webpack 2 no longer allows custom properties in configuration.", + " Loaders should be updated to allow passing options via loader options in module.rules.", + " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:", + " plugins: [", + " new webpack.LoaderOptionsPlugin({", + " // test: /\\.xxx$/, // may apply this only for some modules", + " options: {", + " postcss: ...", + " }", + " })", + " ]" + ] + }, + { + name: "enum", + config: { + entry: "a", + devtool: true + }, + message: [ + " - configuration.devtool should be one of these:", + " string | false", + " -> A developer tool to enhance debugging.", + " Details:", + " * configuration.devtool should be a string.", + " * configuration.devtool should be false" + ] + }, + { + name: "relative path", + config: { + entry: "foo.js", + output: { + filename: "/bar" + } + }, + message: [ + ' - configuration.output.filename: A relative path is expected. However the provided value "/bar" is an absolute path!', + " -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", + " Please use output.path to specify absolute path and output.filename for the file name." + ] + }, + { + name: "absolute path", + config: { + entry: "foo.js", + output: { + filename: "bar" + }, + context: "baz" + }, + message: [ + ' - configuration.context: The provided value "baz" is not an absolute path!', + " -> The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory." + ] + }, + { + name: "missing stats option", + config: { + entry: "foo.js", + stats: { + foobar: true + } + }, + test(err) { + err.message.should.startWith("Invalid configuration object."); + err.message + .split("\n") + .slice(1)[0] + .should.be.eql(" - configuration.stats should be one of these:"); } }, - test(err) { - err.message.should.startWith("Invalid configuration object."); - err.message.split("\n").slice(1)[0].should.be.eql( - " - configuration.stats should be one of these:" - ); + { + name: "Invalid plugin provided: bool", + config: { + entry: "foo.js", + plugins: [false] + }, + message: [ + " - configuration.plugins[0] should be one of these:", + " object { apply, ... } | function", + " -> Plugin of type object or instanceof Function", + " Details:", + " * configuration.plugins[0] should be an object.", + " -> Plugin instance", + " * configuration.plugins[0] should be an instance of function", + " -> Function acting as plugin" + ] + }, + { + name: "Invalid plugin provided: array", + config: { + entry: "foo.js", + plugins: [[]] + }, + message: [ + " - configuration.plugins[0] should be one of these:", + " object { apply, ... } | function", + " -> Plugin of type object or instanceof Function", + " Details:", + " * configuration.plugins[0] should be an object.", + " -> Plugin instance", + " * configuration.plugins[0] should be an instance of function", + " -> Function acting as plugin" + ] + }, + { + name: "Invalid plugin provided: string", + config: { + entry: "foo.js", + plugins: ["abc123"] + }, + message: [ + " - configuration.plugins[0] should be one of these:", + " object { apply, ... } | function", + " -> Plugin of type object or instanceof Function", + " Details:", + " * configuration.plugins[0] should be an object.", + " -> Plugin instance", + " * configuration.plugins[0] should be an instance of function", + " -> Function acting as plugin" + ] + }, + { + name: "Invalid plugin provided: int", + config: { + entry: "foo.js", + plugins: [12] + }, + message: [ + " - configuration.plugins[0] should be one of these:", + " object { apply, ... } | function", + " -> Plugin of type object or instanceof Function", + " Details:", + " * configuration.plugins[0] should be an object.", + " -> Plugin instance", + " * configuration.plugins[0] should be an instance of function", + " -> Function acting as plugin" + ] + }, + { + name: "Invalid plugin provided: object without apply function", + config: { + entry: "foo.js", + plugins: [{}] + }, + message: [ + " - configuration.plugins[0] should be one of these:", + " object { apply, ... } | function", + " -> Plugin of type object or instanceof Function", + " Details:", + " * configuration.plugins[0] misses the property 'apply'.", + " function", + " -> The run point of the plugin, required method.", + " * configuration.plugins[0] misses the property 'apply'.", + " function", + " -> The run point of the plugin, required method.", + " * configuration.plugins[0] should be an instance of function", + " -> Function acting as plugin" + ] } - }, { - name: "Invalid plugin provided: bool", - config: { - entry: "foo.js", - plugins: [ - false - ] - }, - message: [ - " - configuration.plugins[0] should be one of these:", - " object { apply, ... } | function", - " -> Plugin of type object or instanceof Function", - " Details:", - " * configuration.plugins[0] should be an object.", - " -> Plugin instance", - " * configuration.plugins[0] should be an instance of function", - " -> Function acting as plugin" - ] - }, { - name: "Invalid plugin provided: array", - config: { - entry: "foo.js", - plugins: [ - [] - ] - }, - message: [ - " - configuration.plugins[0] should be one of these:", - " object { apply, ... } | function", - " -> Plugin of type object or instanceof Function", - " Details:", - " * configuration.plugins[0] should be an object.", - " -> Plugin instance", - " * configuration.plugins[0] should be an instance of function", - " -> Function acting as plugin" - ] - }, { - name: "Invalid plugin provided: string", - config: { - entry: "foo.js", - plugins: ["abc123"] - }, - message: [ - " - configuration.plugins[0] should be one of these:", - " object { apply, ... } | function", - " -> Plugin of type object or instanceof Function", - " Details:", - " * configuration.plugins[0] should be an object.", - " -> Plugin instance", - " * configuration.plugins[0] should be an instance of function", - " -> Function acting as plugin" - ] - }, { - name: "Invalid plugin provided: int", - config: { - entry: "foo.js", - plugins: [ - 12 - ] - }, - message: [ - " - configuration.plugins[0] should be one of these:", - " object { apply, ... } | function", - " -> Plugin of type object or instanceof Function", - " Details:", - " * configuration.plugins[0] should be an object.", - " -> Plugin instance", - " * configuration.plugins[0] should be an instance of function", - " -> Function acting as plugin" - ] - }, { - name: "Invalid plugin provided: object without apply function", - config: { - entry: "foo.js", - plugins: [{}] - }, - message: [ - " - configuration.plugins[0] should be one of these:", - " object { apply, ... } | function", - " -> Plugin of type object or instanceof Function", - " Details:", - " * configuration.plugins[0] misses the property 'apply'.", - " function", - " -> The run point of the plugin, required method.", - " * configuration.plugins[0] misses the property 'apply'.", - " function", - " -> The run point of the plugin, required method.", - " * configuration.plugins[0] should be an instance of function", - " -> Function acting as plugin" - ] - }]; + ]; - testCases.forEach((testCase) => { + testCases.forEach(testCase => { it("should fail validation for " + testCase.name, () => { try { webpack(testCase.config); - } catch(err) { - if(err.name !== "WebpackOptionsValidationError") throw err; + } catch (err) { + if (err.name !== "WebpackOptionsValidationError") throw err; - if(testCase.test) { + if (testCase.test) { testCase.test(err); return; } err.message.should.startWith("Invalid configuration object."); - err.message.split("\n").slice(1).should.be.eql(testCase.message); + err.message + .split("\n") + .slice(1) + .should.be.eql(testCase.message); return; } diff --git a/test/WatchDetection.test.js b/test/WatchDetection.test.js index d34ff7d63..fcdd6601d 100644 --- a/test/WatchDetection.test.js +++ b/test/WatchDetection.test.js @@ -9,47 +9,51 @@ const MemoryFs = require("memory-fs"); const webpack = require("../"); describe("WatchDetection", () => { - if(process.env.NO_WATCH_TESTS) { + if (process.env.NO_WATCH_TESTS) { it("long running tests excluded"); return; } - for(let changeTimeout = 0; changeTimeout < 100; changeTimeout += 10) { + for (let changeTimeout = 0; changeTimeout < 100; changeTimeout += 10) { createTestCase(changeTimeout); } - for(let changeTimeout = 100; changeTimeout <= 2000; changeTimeout += 100) { + for (let changeTimeout = 100; changeTimeout <= 2000; changeTimeout += 100) { createTestCase(changeTimeout); } function createTestCase(changeTimeout) { describe("time between changes " + changeTimeout + "ms", function() { this.timeout(10000); - const fixturePath = path.join(__dirname, "fixtures", "temp-" + changeTimeout); + const fixturePath = path.join( + __dirname, + "fixtures", + "temp-" + changeTimeout + ); const filePath = path.join(fixturePath, "file.js"); const file2Path = path.join(fixturePath, "file2.js"); const loaderPath = path.join(__dirname, "fixtures", "delay-loader.js"); before(() => { try { fs.mkdirSync(fixturePath); - } catch(e) {} + } catch (e) {} fs.writeFileSync(filePath, "require('./file2')", "utf-8"); fs.writeFileSync(file2Path, "original", "utf-8"); }); - after((done) => { + after(done => { setTimeout(() => { try { fs.unlinkSync(filePath); - } catch(e) {} + } catch (e) {} try { fs.unlinkSync(file2Path); - } catch(e) {} + } catch (e) {} try { fs.rmdirSync(fixturePath); - } catch(e) {} + } catch (e) {} done(); }, 100); // cool down a bit }); - it("should build the bundle correctly", (done) => { + it("should build the bundle correctly", done => { const compiler = webpack({ entry: loaderPath + "!" + filePath, output: { @@ -57,11 +61,10 @@ describe("WatchDetection", () => { filename: "bundle.js" } }); - const memfs = compiler.outputFileSystem = new MemoryFs(); + const memfs = (compiler.outputFileSystem = new MemoryFs()); let onChange; compiler.hooks.done.tap("WatchDetectionTest", () => { - if(onChange) - onChange(); + if (onChange) onChange(); }); let watcher; @@ -70,19 +73,33 @@ describe("WatchDetection", () => { function step1() { onChange = () => { - if(memfs.readFileSync("/bundle.js") && memfs.readFileSync("/bundle.js").toString().indexOf("original") >= 0) + if ( + memfs.readFileSync("/bundle.js") && + memfs + .readFileSync("/bundle.js") + .toString() + .indexOf("original") >= 0 + ) step2(); }; - watcher = compiler.watch({ - aggregateTimeout: 50 - }, () => {}); + watcher = compiler.watch( + { + aggregateTimeout: 50 + }, + () => {} + ); } function step2() { onChange = null; - fs.writeFile(filePath, "require('./file2'); again", "utf-8", handleError); + fs.writeFile( + filePath, + "require('./file2'); again", + "utf-8", + handleError + ); setTimeout(step3, changeTimeout); } @@ -97,7 +114,12 @@ describe("WatchDetection", () => { function step4() { onChange = () => { - if(memfs.readFileSync("/bundle.js").toString().indexOf("correct") >= 0) + if ( + memfs + .readFileSync("/bundle.js") + .toString() + .indexOf("correct") >= 0 + ) step5(); }; @@ -113,7 +135,7 @@ describe("WatchDetection", () => { } function handleError(err) { - if(err) done(err); + if (err) done(err); } }); }); diff --git a/test/WatchTestCases.test.js b/test/WatchTestCases.test.js index 5acd39b39..82e3bf8a7 100644 --- a/test/WatchTestCases.test.js +++ b/test/WatchTestCases.test.js @@ -12,33 +12,30 @@ const Stats = require("../lib/Stats"); const webpack = require("../lib/webpack"); function copyDiff(src, dest) { - if(!fs.existsSync(dest)) - fs.mkdirSync(dest); + if (!fs.existsSync(dest)) fs.mkdirSync(dest); const files = fs.readdirSync(src); - files.forEach((filename) => { + files.forEach(filename => { const srcFile = path.join(src, filename); const destFile = path.join(dest, filename); const directory = fs.statSync(srcFile).isDirectory(); - if(directory) { + if (directory) { copyDiff(srcFile, destFile); } else { var content = fs.readFileSync(srcFile); - if(/^DELETE\s*$/.test(content.toString("utf-8"))) + if (/^DELETE\s*$/.test(content.toString("utf-8"))) fs.unlinkSync(destFile); - else - fs.writeFileSync(destFile, content); + else fs.writeFileSync(destFile, content); } }); } function remove(src) { - if(!fs.existsSync(src)) - return; + if (!fs.existsSync(src)) return; const files = fs.readdirSync(src); - files.forEach((filename) => { + files.forEach(filename => { const srcFile = path.join(src, filename); const directory = fs.statSync(srcFile).isDirectory(); - if(directory) { + if (directory) { remove(srcFile); } else { fs.unlinkSync(srcFile); @@ -47,7 +44,7 @@ function remove(src) { } describe("WatchTestCases", () => { - if(process.env.NO_WATCH_TESTS) { + if (process.env.NO_WATCH_TESTS) { it("long running tests excluded"); return; } @@ -55,59 +52,76 @@ describe("WatchTestCases", () => { const casesPath = path.join(__dirname, "watchCases"); let categories = fs.readdirSync(casesPath); - categories = categories.map((cat) => { + categories = categories.map(cat => { return { name: cat, - tests: fs.readdirSync(path.join(casesPath, cat)).filter((folder) => folder.indexOf("_") < 0).sort() + tests: fs + .readdirSync(path.join(casesPath, cat)) + .filter(folder => folder.indexOf("_") < 0) + .sort() }; }); before(() => { let dest = path.join(__dirname, "js"); - if(!fs.existsSync(dest)) - fs.mkdirSync(dest); + if (!fs.existsSync(dest)) fs.mkdirSync(dest); dest = path.join(__dirname, "js", "watch-src"); - if(!fs.existsSync(dest)) - fs.mkdirSync(dest); + if (!fs.existsSync(dest)) fs.mkdirSync(dest); }); - categories.forEach((category) => { + categories.forEach(category => { before(() => { const dest = path.join(__dirname, "js", "watch-src", category.name); - if(!fs.existsSync(dest)) - fs.mkdirSync(dest); + if (!fs.existsSync(dest)) fs.mkdirSync(dest); }); describe(category.name, () => { - category.tests.forEach((testName) => { + category.tests.forEach(testName => { describe(testName, () => { - const tempDirectory = path.join(__dirname, "js", "watch-src", category.name, testName); + const tempDirectory = path.join( + __dirname, + "js", + "watch-src", + category.name, + testName + ); const testDirectory = path.join(casesPath, category.name, testName); - const runs = fs.readdirSync(testDirectory).sort().filter((name) => { - return fs.statSync(path.join(testDirectory, name)).isDirectory(); - }).map((name) => { - return { - name: name, - suite: describe(name, () => {}) - }; - }); + const runs = fs + .readdirSync(testDirectory) + .sort() + .filter(name => { + return fs.statSync(path.join(testDirectory, name)).isDirectory(); + }) + .map(name => { + return { + name: name, + suite: describe(name, () => {}) + }; + }); before(() => remove(tempDirectory)); it("should compile", function(done) { this.timeout(45000); - const outputDirectory = path.join(__dirname, "js", "watch", category.name, testName); + const outputDirectory = path.join( + __dirname, + "js", + "watch", + category.name, + testName + ); let options = {}; const configPath = path.join(testDirectory, "webpack.config.js"); - if(fs.existsSync(configPath)) - options = require(configPath); - const applyConfig = (options) => { - if(!options.mode) options.mode = "development"; - if(!options.context) options.context = tempDirectory; - if(!options.entry) options.entry = "./index.js"; - if(!options.target) options.target = "async-node"; - if(!options.output) options.output = {}; - if(!options.output.path) options.output.path = outputDirectory; - if(typeof options.output.pathinfo === "undefined") options.output.pathinfo = true; - if(!options.output.filename) options.output.filename = "bundle.js"; + if (fs.existsSync(configPath)) options = require(configPath); + const applyConfig = options => { + if (!options.mode) options.mode = "development"; + if (!options.context) options.context = tempDirectory; + if (!options.entry) options.entry = "./index.js"; + if (!options.target) options.target = "async-node"; + if (!options.output) options.output = {}; + if (!options.output.path) options.output.path = outputDirectory; + if (typeof options.output.pathinfo === "undefined") + options.output.pathinfo = true; + if (!options.output.filename) + options.output.filename = "bundle.js"; }; - if(Array.isArray(options)) { + if (Array.isArray(options)) { options.forEach(applyConfig); } else { applyConfig(options); @@ -125,102 +139,180 @@ describe("WatchTestCases", () => { setTimeout(() => { const compiler = webpack(options); - compiler.hooks.invalid.tap("WatchTestCasesTest", (filename, mtime) => { - triggeringFilename = filename; - }); - const watching = compiler.watch({ - aggregateTimeout: 1000 - }, (err, stats) => { - if(err) - return done(err); - if(!stats) - return done(new Error("No stats reported from Compiler")); - if(stats.hash === lastHash) - return; - lastHash = stats.hash; - if(run.done && lastHash !== stats.hash) { - return done(new Error("Compilation changed but no change was issued " + lastHash + " != " + stats.hash + " (run " + runIdx + ")\n" + - "Triggering change: " + triggeringFilename)); + compiler.hooks.invalid.tap( + "WatchTestCasesTest", + (filename, mtime) => { + triggeringFilename = filename; } - if(waitMode) return; - run.done = true; - if(err) return done(err); - const statOptions = Stats.presetToOptions("verbose"); - statOptions.colors = false; - mkdirp.sync(outputDirectory); - fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8"); - const jsonStats = stats.toJson({ - errorDetails: true - }); - if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "error", "Error", done)) return; - if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "warning", "Warning", done)) return; - let exportedTests = 0; + ); + const watching = compiler.watch( + { + aggregateTimeout: 1000 + }, + (err, stats) => { + if (err) return done(err); + if (!stats) + return done(new Error("No stats reported from Compiler")); + if (stats.hash === lastHash) return; + lastHash = stats.hash; + if (run.done && lastHash !== stats.hash) { + return done( + new Error( + "Compilation changed but no change was issued " + + lastHash + + " != " + + stats.hash + + " (run " + + runIdx + + ")\n" + + "Triggering change: " + + triggeringFilename + ) + ); + } + if (waitMode) return; + run.done = true; + if (err) return done(err); + const statOptions = Stats.presetToOptions("verbose"); + statOptions.colors = false; + mkdirp.sync(outputDirectory); + fs.writeFileSync( + path.join(outputDirectory, "stats.txt"), + stats.toString(statOptions), + "utf-8" + ); + const jsonStats = stats.toJson({ + errorDetails: true + }); + if ( + checkArrayExpectation( + path.join(testDirectory, run.name), + jsonStats, + "error", + "Error", + done + ) + ) + return; + if ( + checkArrayExpectation( + path.join(testDirectory, run.name), + jsonStats, + "warning", + "Warning", + done + ) + ) + return; + let exportedTests = 0; - function _it(title, fn) { - const test = new Test(title, fn); - run.suite.addTest(test); - exportedTests++; - return test; + function _it(title, fn) { + const test = new Test(title, fn); + run.suite.addTest(test); + exportedTests++; + return test; + } + + const globalContext = { + console: console + }; + + function _require(currentDirectory, module) { + if (Array.isArray(module) || /^\.\.?\//.test(module)) { + let fn; + let content; + let p; + if (Array.isArray(module)) { + p = path.join(currentDirectory, module[0]); + content = module + .map(arg => { + p = path.join(currentDirectory, arg); + return fs.readFileSync(p, "utf-8"); + }) + .join("\n"); + } else { + p = path.join(currentDirectory, module); + content = fs.readFileSync(p, "utf-8"); + } + if ( + options.target === "web" || + options.target === "webworker" + ) { + fn = vm.runInNewContext( + "(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE, window) {" + + content + + "\n})", + globalContext, + p + ); + } else { + fn = vm.runInThisContext( + "(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE) {" + + content + + "\n})", + p + ); + } + const m = { + exports: {} + }; + fn.call( + m.exports, + _require.bind(null, path.dirname(p)), + m, + m.exports, + path.dirname(p), + p, + _it, + run.name, + jsonStats, + state, + globalContext + ); + return module.exports; + } else if ( + testConfig.modules && + module in testConfig.modules + ) { + return testConfig.modules[module]; + } else return require(module); + } + + let testConfig = {}; + try { + // try to load a test file + testConfig = require(path.join( + testDirectory, + "test.config.js" + )); + } catch (e) {} + + if (testConfig.noTests) return process.nextTick(done); + _require( + outputDirectory, + testConfig.bundlePath || "./bundle.js" + ); + + if (exportedTests < 1) + return done(new Error("No tests exported by test case")); + runIdx++; + if (runIdx < runs.length) { + run = runs[runIdx]; + waitMode = true; + setTimeout(() => { + waitMode = false; + currentWatchStepModule.step = run.name; + copyDiff( + path.join(testDirectory, run.name), + tempDirectory + ); + }, 1500); + } else { + watching.close(); + process.nextTick(done); + } } - - const globalContext = { - console: console - }; - - function _require(currentDirectory, module) { - if(Array.isArray(module) || /^\.\.?\//.test(module)) { - let fn; - let content; - let p; - if(Array.isArray(module)) { - p = path.join(currentDirectory, module[0]); - content = module.map((arg) => { - p = path.join(currentDirectory, arg); - return fs.readFileSync(p, "utf-8"); - }).join("\n"); - } else { - p = path.join(currentDirectory, module); - content = fs.readFileSync(p, "utf-8"); - } - if(options.target === "web" || options.target === "webworker") { - fn = vm.runInNewContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE, window) {" + content + "\n})", globalContext, p); - } else { - fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE) {" + content + "\n})", p); - } - const m = { - exports: {} - }; - fn.call(m.exports, _require.bind(null, path.dirname(p)), m, m.exports, path.dirname(p), p, _it, run.name, jsonStats, state, globalContext); - return module.exports; - } else if(testConfig.modules && module in testConfig.modules) { - return testConfig.modules[module]; - } else return require(module); - } - - let testConfig = {}; - try { - // try to load a test file - testConfig = require(path.join(testDirectory, "test.config.js")); - } catch(e) {} - - if(testConfig.noTests) return process.nextTick(done); - _require(outputDirectory, testConfig.bundlePath || "./bundle.js"); - - if(exportedTests < 1) return done(new Error("No tests exported by test case")); - runIdx++; - if(runIdx < runs.length) { - run = runs[runIdx]; - waitMode = true; - setTimeout(() => { - waitMode = false; - currentWatchStepModule.step = run.name; - copyDiff(path.join(testDirectory, run.name), tempDirectory); - }, 1500); - } else { - watching.close(); - process.nextTick(done); - } - }); + ); }, 300); }); }); diff --git a/test/WatcherEvents.test.js b/test/WatcherEvents.test.js index da9fd3398..641e9b44d 100644 --- a/test/WatcherEvents.test.js +++ b/test/WatcherEvents.test.js @@ -20,21 +20,25 @@ const createSingleCompiler = () => { }; const createMultiCompiler = () => { - return createCompiler([{ - context: path.join(__dirname, "fixtures"), - entry: "./a.js" - }]); + return createCompiler([ + { + context: path.join(__dirname, "fixtures"), + entry: "./a.js" + } + ]); }; describe("WatcherEvents", function() { - if(process.env.NO_WATCH_TESTS) { + if (process.env.NO_WATCH_TESTS) { it("long running tests excluded"); return; } this.timeout(10000); - it("should emit 'watch-close' when using single-compiler mode and the compiler is not running", function(done) { + it("should emit 'watch-close' when using single-compiler mode and the compiler is not running", function( + done + ) { let called = false; const compiler = createSingleCompiler(); @@ -50,10 +54,11 @@ describe("WatcherEvents", function() { compiler.hooks.done.tap("WatcherEventsTest", () => { watcher.close(); }); - }); - it("should emit 'watch-close' when using multi-compiler mode and the compiler is not running", function(done) { + it("should emit 'watch-close' when using multi-compiler mode and the compiler is not running", function( + done + ) { let called = false; const compiler = createMultiCompiler(); @@ -69,7 +74,5 @@ describe("WatcherEvents", function() { compiler.hooks.done.tap("WatcherEventsTest", () => { watcher.close(); }); - }); - }); diff --git a/test/WebEnvironmentPlugin.unittest.js b/test/WebEnvironmentPlugin.unittest.js index 1cd44db05..146b1f277 100644 --- a/test/WebEnvironmentPlugin.unittest.js +++ b/test/WebEnvironmentPlugin.unittest.js @@ -6,7 +6,13 @@ const WebEnvironmentPlugin = require("../lib/web/WebEnvironmentPlugin"); describe("WebEnvironmentPlugin", () => { let WebEnvironmentPluginInstance; - before(() => WebEnvironmentPluginInstance = new WebEnvironmentPlugin("inputFileSystem", "outputFileSystem")); + before( + () => + (WebEnvironmentPluginInstance = new WebEnvironmentPlugin( + "inputFileSystem", + "outputFileSystem" + )) + ); describe("apply", () => { let compileSpy; @@ -18,6 +24,8 @@ describe("WebEnvironmentPlugin", () => { }); it("should set compiler.outputFileSystem information with the same as setted in WebEnvironmentPlugin", () => - should(compileSpy.outputFileSystem).be.eql(WebEnvironmentPluginInstance.outputFileSystem)); + should(compileSpy.outputFileSystem).be.eql( + WebEnvironmentPluginInstance.outputFileSystem + )); }); }); diff --git a/test/WebpackMissingModule.unittest.js b/test/WebpackMissingModule.unittest.js index ce82d7771..c08f978da 100644 --- a/test/WebpackMissingModule.unittest.js +++ b/test/WebpackMissingModule.unittest.js @@ -8,21 +8,27 @@ describe("WebpackMissingModule", () => { describe("#moduleCode", () => { it("returns an error message based on given error message", () => { const errorMessage = WebpackMissingModule.moduleCode("mock message"); - should(errorMessage).be.eql("var e = new Error(\"Cannot find module \\\"mock message\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e;"); + should(errorMessage).be.eql( + 'var e = new Error("Cannot find module \\"mock message\\""); e.code = \'MODULE_NOT_FOUND\'; throw e;' + ); }); }); describe("#promise", () => { it("returns an error message based on given error message", () => { const errorMessage = WebpackMissingModule.promise("mock message"); - should(errorMessage).be.eql("Promise.reject(function webpackMissingModule() { var e = new Error(\"Cannot find module \\\"mock message\\\"\"); e.code = 'MODULE_NOT_FOUND'; return e; }())"); + should(errorMessage).be.eql( + 'Promise.reject(function webpackMissingModule() { var e = new Error("Cannot find module \\"mock message\\""); e.code = \'MODULE_NOT_FOUND\'; return e; }())' + ); }); }); describe("#module", () => { it("returns an error message based on given error message", () => { const errorMessage = WebpackMissingModule.module("mock message"); - should(errorMessage).be.eql("!(function webpackMissingModule() { var e = new Error(\"Cannot find module \\\"mock message\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e; }())"); + should(errorMessage).be.eql( + '!(function webpackMissingModule() { var e = new Error("Cannot find module \\"mock message\\""); e.code = \'MODULE_NOT_FOUND\'; throw e; }())' + ); }); }); }); diff --git a/test/browsertest/webpack.config.js b/test/browsertest/webpack.config.js index c587c31d7..ee9f01b36 100644 --- a/test/browsertest/webpack.config.js +++ b/test/browsertest/webpack.config.js @@ -4,7 +4,13 @@ module.exports = { extensions: [".json", ".web.js", ".js"] }, resolveLoader: { - extensions: [".json", ".webpack-loader.js", ".web-loader.js", ".loader.js", ".js"], + extensions: [ + ".json", + ".webpack-loader.js", + ".web-loader.js", + ".loader.js", + ".js" + ], mainFields: ["webpackLoader", "loader", "main"] } }; diff --git a/test/checkArrayExpectation.js b/test/checkArrayExpectation.js index 846af096a..353f3df78 100644 --- a/test/checkArrayExpectation.js +++ b/test/checkArrayExpectation.js @@ -2,31 +2,80 @@ const fs = require("fs"); const path = require("path"); -module.exports = function checkArrayExpectation(testDirectory, object, kind, filename, upperCaseKind, done) { - if(!done) { +module.exports = function checkArrayExpectation( + testDirectory, + object, + kind, + filename, + upperCaseKind, + done +) { + if (!done) { done = upperCaseKind; upperCaseKind = filename; filename = `${kind}s`; } let array = object[`${kind}s`].slice().sort(); - if(kind === "warning") array = array.filter(item => !/from UglifyJs/.test(item)); - if(fs.existsSync(path.join(testDirectory, `${filename}.js`))) { + if (kind === "warning") + array = array.filter(item => !/from UglifyJs/.test(item)); + if (fs.existsSync(path.join(testDirectory, `${filename}.js`))) { const expectedFilename = path.join(testDirectory, `${filename}.js`); const expected = require(expectedFilename); - if(expected.length < array.length) - return done(new Error(`More ${kind}s while compiling than expected:\n\n${array.join("\n\n")}. Check expected warnings: ${filename}`)), true; - else if(expected.length > array.length) - return done(new Error(`Less ${kind}s while compiling than expected:\n\n${array.join("\n\n")}. Check expected warnings: ${filename}`)), true; - for(let i = 0; i < array.length; i++) { - if(Array.isArray(expected[i])) { - for(let j = 0; j < expected[i].length; j++) { - if(!expected[i][j].test(array[i])) - return done(new Error(`${upperCaseKind} ${i}: ${array[i]} doesn't match ${expected[i][j].toString()}`)), true; + if (expected.length < array.length) + return ( + done( + new Error( + `More ${kind}s while compiling than expected:\n\n${array.join( + "\n\n" + )}. Check expected warnings: ${filename}` + ) + ), + true + ); + else if (expected.length > array.length) + return ( + done( + new Error( + `Less ${kind}s while compiling than expected:\n\n${array.join( + "\n\n" + )}. Check expected warnings: ${filename}` + ) + ), + true + ); + for (let i = 0; i < array.length; i++) { + if (Array.isArray(expected[i])) { + for (let j = 0; j < expected[i].length; j++) { + if (!expected[i][j].test(array[i])) + return ( + done( + new Error( + `${upperCaseKind} ${i}: ${array[i]} doesn't match ${expected[ + i + ][j].toString()}` + ) + ), + true + ); } - } else if(!expected[i].test(array[i])) - return done(new Error(`${upperCaseKind} ${i}: ${array[i]} doesn't match ${expected[i].toString()}`)), true; + } else if (!expected[i].test(array[i])) + return ( + done( + new Error( + `${upperCaseKind} ${i}: ${array[i]} doesn't match ${expected[ + i + ].toString()}` + ) + ), + true + ); } - } else if(array.length > 0) { - return done(new Error(`${upperCaseKind}s while compiling:\n\n${array.join("\n\n")}`)), true; + } else if (array.length > 0) { + return ( + done( + new Error(`${upperCaseKind}s while compiling:\n\n${array.join("\n\n")}`) + ), + true + ); } }; diff --git a/test/compareLocations.unittest.js b/test/compareLocations.unittest.js index c378182aa..5efc5d3de 100644 --- a/test/compareLocations.unittest.js +++ b/test/compareLocations.unittest.js @@ -3,10 +3,13 @@ const should = require("should"); const compareLocations = require("../lib/compareLocations"); const createPosition = function(overides) { - return Object.assign({ - line: 10, - column: 5 - }, overides); + return Object.assign( + { + line: 10, + column: 5 + }, + overides + ); }; const createLocation = function(start, end, index) { @@ -115,6 +118,5 @@ describe("compareLocations", () => { it("returns undefined when both the first parameter and the second parameter is a number", () => should(compareLocations(123, 456)).be.undefined()); - }); }); diff --git a/test/configCases/additional-pass/simple/webpack.config.js b/test/configCases/additional-pass/simple/webpack.config.js index c16b2da81..398236f46 100644 --- a/test/configCases/additional-pass/simple/webpack.config.js +++ b/test/configCases/additional-pass/simple/webpack.config.js @@ -3,14 +3,11 @@ var testPlugin = function() { this.hooks.compilation.tap("TestPlugin", compilation => { var nr = counter++; compilation.hooks.needAdditionalPass.tap("TestPlugin", function() { - if(nr < 5) - return true; + if (nr < 5) return true; }); }); }; module.exports = { - plugins: [ - testPlugin - ] + plugins: [testPlugin] }; diff --git a/test/configCases/async-commons-chunk/existing-name/webpack.config.js b/test/configCases/async-commons-chunk/existing-name/webpack.config.js index 6eb4fd571..99f63ca81 100644 --- a/test/configCases/async-commons-chunk/existing-name/webpack.config.js +++ b/test/configCases/async-commons-chunk/existing-name/webpack.config.js @@ -10,7 +10,5 @@ module.exports = { name: true } }, - plugins: [ - new webpack.NamedChunksPlugin() - ] + plugins: [new webpack.NamedChunksPlugin()] }; diff --git a/test/configCases/code-generation/require-context-id/webpack.config.js b/test/configCases/code-generation/require-context-id/webpack.config.js index 5eb2dc652..68fbeb157 100644 --- a/test/configCases/code-generation/require-context-id/webpack.config.js +++ b/test/configCases/code-generation/require-context-id/webpack.config.js @@ -1,6 +1,4 @@ var webpack = require("../../../../"); module.exports = { - plugins: [ - new webpack.HashedModuleIdsPlugin() - ] + plugins: [new webpack.HashedModuleIdsPlugin()] }; diff --git a/test/configCases/commons-chunk-plugin/hot-multi/webpack.config.js b/test/configCases/commons-chunk-plugin/hot-multi/webpack.config.js index 912d47e42..55d33b816 100644 --- a/test/configCases/commons-chunk-plugin/hot-multi/webpack.config.js +++ b/test/configCases/commons-chunk-plugin/hot-multi/webpack.config.js @@ -15,7 +15,5 @@ module.exports = { name: "vendor" } }, - plugins: [ - new HotModuleReplacementPlugin() - ] + plugins: [new HotModuleReplacementPlugin()] }; diff --git a/test/configCases/commons-chunk-plugin/hot/webpack.config.js b/test/configCases/commons-chunk-plugin/hot/webpack.config.js index f60e02d4b..868db8df3 100644 --- a/test/configCases/commons-chunk-plugin/hot/webpack.config.js +++ b/test/configCases/commons-chunk-plugin/hot/webpack.config.js @@ -14,7 +14,5 @@ module.exports = { name: "vendor" } }, - plugins: [ - new HotModuleReplacementPlugin() - ] + plugins: [new HotModuleReplacementPlugin()] }; diff --git a/test/configCases/commons-chunk-plugin/move-to-grandparent/webpack.config.js b/test/configCases/commons-chunk-plugin/move-to-grandparent/webpack.config.js index 7b5eba71c..520f039b2 100644 --- a/test/configCases/commons-chunk-plugin/move-to-grandparent/webpack.config.js +++ b/test/configCases/commons-chunk-plugin/move-to-grandparent/webpack.config.js @@ -1,7 +1,7 @@ module.exports = { entry: { main: "./index", - misc: "./second", + misc: "./second" }, output: { filename: "[name].js" diff --git a/test/configCases/compiletime/warn-not-found/webpack.config.js b/test/configCases/compiletime/warn-not-found/webpack.config.js index 8b1378917..e69de29bb 100644 --- a/test/configCases/compiletime/warn-not-found/webpack.config.js +++ b/test/configCases/compiletime/warn-not-found/webpack.config.js @@ -1 +0,0 @@ - diff --git a/test/configCases/context-exclusion/simple/webpack.config.js b/test/configCases/context-exclusion/simple/webpack.config.js index 9c828d3bc..914088d01 100644 --- a/test/configCases/context-exclusion/simple/webpack.config.js +++ b/test/configCases/context-exclusion/simple/webpack.config.js @@ -1,7 +1,5 @@ var webpack = require("../../../../"); module.exports = { - plugins: [ - new webpack.ContextExclusionPlugin(/dont/) - ] + plugins: [new webpack.ContextExclusionPlugin(/dont/)] }; diff --git a/test/configCases/context-replacement/System.import/webpack.config.js b/test/configCases/context-replacement/System.import/webpack.config.js index 83e23c343..dd3a95923 100644 --- a/test/configCases/context-replacement/System.import/webpack.config.js +++ b/test/configCases/context-replacement/System.import/webpack.config.js @@ -3,8 +3,12 @@ var webpack = require("../../../../"); module.exports = { plugins: [ - new webpack.ContextReplacementPlugin(/context-replacement/, path.resolve(__dirname, "modules"), { - "a": "./module-b" - }) + new webpack.ContextReplacementPlugin( + /context-replacement/, + path.resolve(__dirname, "modules"), + { + a: "./module-b" + } + ) ] }; diff --git a/test/configCases/context-replacement/a/webpack.config.js b/test/configCases/context-replacement/a/webpack.config.js index 0f90c0064..effb49f41 100644 --- a/test/configCases/context-replacement/a/webpack.config.js +++ b/test/configCases/context-replacement/a/webpack.config.js @@ -2,6 +2,11 @@ var webpack = require("../../../../"); module.exports = { plugins: [ - new webpack.ContextReplacementPlugin(/context-replacement.a$/, "new-context", true, /^replaced$/) + new webpack.ContextReplacementPlugin( + /context-replacement.a$/, + "new-context", + true, + /^replaced$/ + ) ] }; diff --git a/test/configCases/context-replacement/c/webpack.config.js b/test/configCases/context-replacement/c/webpack.config.js index 165de834a..6a7c2c314 100644 --- a/test/configCases/context-replacement/c/webpack.config.js +++ b/test/configCases/context-replacement/c/webpack.config.js @@ -3,12 +3,16 @@ var webpack = require("../../../../"); module.exports = { plugins: [ - new webpack.ContextReplacementPlugin(/context-replacement.c$/, path.resolve(__dirname, "modules"), { - "a": "./a", - "b": "./module-b", - "./c": "./module-b", - "d": "d", - "./d": "d" - }) + new webpack.ContextReplacementPlugin( + /context-replacement.c$/, + path.resolve(__dirname, "modules"), + { + a: "./a", + b: "./module-b", + "./c": "./module-b", + d: "d", + "./d": "d" + } + ) ] }; diff --git a/test/configCases/context-replacement/d/webpack.config.js b/test/configCases/context-replacement/d/webpack.config.js index 7e17408f2..21b667c52 100644 --- a/test/configCases/context-replacement/d/webpack.config.js +++ b/test/configCases/context-replacement/d/webpack.config.js @@ -3,16 +3,20 @@ var webpack = require("../../../../"); module.exports = { module: { - rules: [{ - test: /a\.js$/, - use: [ - "./queryloader?lions=roar" - ] - }] + rules: [ + { + test: /a\.js$/, + use: ["./queryloader?lions=roar"] + } + ] }, plugins: [ - new webpack.ContextReplacementPlugin(/context-replacement.d$/, path.resolve(__dirname, "modules?cats=meow"), { - "a": "./a", - }) + new webpack.ContextReplacementPlugin( + /context-replacement.d$/, + path.resolve(__dirname, "modules?cats=meow"), + { + a: "./a" + } + ) ] }; diff --git a/test/configCases/custom-hash-function/xxhash/webpack.config.js b/test/configCases/custom-hash-function/xxhash/webpack.config.js index e0d637e79..b2d734eab 100644 --- a/test/configCases/custom-hash-function/xxhash/webpack.config.js +++ b/test/configCases/custom-hash-function/xxhash/webpack.config.js @@ -1,5 +1,7 @@ -module.exports = [{ - output: { - hashFunction: require("xxhashjs").h32 +module.exports = [ + { + output: { + hashFunction: require("xxhashjs").h32 + } } -}]; +]; diff --git a/test/configCases/dll-plugin/0-create-dll/webpack.config.js b/test/configCases/dll-plugin/0-create-dll/webpack.config.js index cfde6b0d9..af773ff4f 100644 --- a/test/configCases/dll-plugin/0-create-dll/webpack.config.js +++ b/test/configCases/dll-plugin/0-create-dll/webpack.config.js @@ -12,17 +12,22 @@ module.exports = { libraryTarget: "commonjs2" }, module: { - rules: [{ - test: /\.abc\.js$/, - loader: "./g-loader.js", - options: { - test: 1 + rules: [ + { + test: /\.abc\.js$/, + loader: "./g-loader.js", + options: { + test: 1 + } } - }] + ] }, plugins: [ new webpack.DllPlugin({ - path: path.resolve(__dirname, "../../../js/config/dll-plugin/manifest0.json") + path: path.resolve( + __dirname, + "../../../js/config/dll-plugin/manifest0.json" + ) }) ] }; diff --git a/test/configCases/dll-plugin/2-use-dll-without-scope/webpack.config.js b/test/configCases/dll-plugin/2-use-dll-without-scope/webpack.config.js index 1bec53ab3..4e5545d2d 100644 --- a/test/configCases/dll-plugin/2-use-dll-without-scope/webpack.config.js +++ b/test/configCases/dll-plugin/2-use-dll-without-scope/webpack.config.js @@ -3,15 +3,19 @@ var webpack = require("../../../../"); module.exports = { module: { - rules: [{ - oneOf: [{ - test: /\.abc\.js$/, - loader: "../0-create-dll/g-loader.js", - options: { - test: 1 - } - }] - }] + rules: [ + { + oneOf: [ + { + test: /\.abc\.js$/, + loader: "../0-create-dll/g-loader.js", + options: { + test: 1 + } + } + ] + } + ] }, resolve: { extensions: [".js", ".jsx"] diff --git a/test/configCases/dll-plugin/3-use-dll-with-hashid/webpack.config.js b/test/configCases/dll-plugin/3-use-dll-with-hashid/webpack.config.js index cf7b6b059..9b07dd08d 100644 --- a/test/configCases/dll-plugin/3-use-dll-with-hashid/webpack.config.js +++ b/test/configCases/dll-plugin/3-use-dll-with-hashid/webpack.config.js @@ -3,15 +3,19 @@ var webpack = require("../../../../"); module.exports = { module: { - rules: [{ - oneOf: [{ - test: /\.abc\.js$/, - loader: "../0-create-dll/g-loader.js", - options: { - test: 1 - } - }] - }] + rules: [ + { + oneOf: [ + { + test: /\.abc\.js$/, + loader: "../0-create-dll/g-loader.js", + options: { + test: 1 + } + } + ] + } + ] }, plugins: [ new webpack.DllReferencePlugin({ @@ -20,6 +24,6 @@ module.exports = { context: path.resolve(__dirname, "../0-create-dll"), sourceType: "commonjs2" }), - new webpack.HashedModuleIdsPlugin(), + new webpack.HashedModuleIdsPlugin() ] }; diff --git a/test/configCases/errors/multi-entry-missing-module/webpack.config.js b/test/configCases/errors/multi-entry-missing-module/webpack.config.js index e87e19561..221fe4b45 100644 --- a/test/configCases/errors/multi-entry-missing-module/webpack.config.js +++ b/test/configCases/errors/multi-entry-missing-module/webpack.config.js @@ -7,9 +7,7 @@ module.exports = { output: { filename: "[name].js" }, - plugins: [ - new IgnorePlugin(new RegExp(/intentionally-missing-module/)) - ], + plugins: [new IgnorePlugin(new RegExp(/intentionally-missing-module/))], node: { __dirname: false } diff --git a/test/configCases/filename-template/module-filename-template/webpack.config.js b/test/configCases/filename-template/module-filename-template/webpack.config.js index 3d78a4164..a5e99ca66 100644 --- a/test/configCases/filename-template/module-filename-template/webpack.config.js +++ b/test/configCases/filename-template/module-filename-template/webpack.config.js @@ -11,5 +11,4 @@ module.exports = { __filename: false }, devtool: "cheap-source-map" - }; diff --git a/test/configCases/hash-length/hashed-module-ids/webpack.config.js b/test/configCases/hash-length/hashed-module-ids/webpack.config.js index 39aa6dd23..a0d852129 100644 --- a/test/configCases/hash-length/hashed-module-ids/webpack.config.js +++ b/test/configCases/hash-length/hashed-module-ids/webpack.config.js @@ -1,22 +1,26 @@ var webpack = require("../../../../"); -module.exports = [{ - plugins: [ - new webpack.HashedModuleIdsPlugin({ - hashDigestLength: 2 - }) - ] -}, { - plugins: [ - new webpack.HashedModuleIdsPlugin({ - hashDigest: "hex", - hashDigestLength: 2 - }) - ] -}, { - plugins: [ - new webpack.HashedModuleIdsPlugin({ - hashFunction: "sha1", - hashDigestLength: 3 - }) - ] -}]; +module.exports = [ + { + plugins: [ + new webpack.HashedModuleIdsPlugin({ + hashDigestLength: 2 + }) + ] + }, + { + plugins: [ + new webpack.HashedModuleIdsPlugin({ + hashDigest: "hex", + hashDigestLength: 2 + }) + ] + }, + { + plugins: [ + new webpack.HashedModuleIdsPlugin({ + hashFunction: "sha1", + hashDigestLength: 3 + }) + ] + } +]; diff --git a/test/configCases/hash-length/output-filename/webpack.config.js b/test/configCases/hash-length/output-filename/webpack.config.js index e8395c6a3..b158b7f0b 100644 --- a/test/configCases/hash-length/output-filename/webpack.config.js +++ b/test/configCases/hash-length/output-filename/webpack.config.js @@ -1,6 +1,5 @@ var webpack = require("../../../../"); module.exports = [ - { name: "hash with length in publicPath", output: { @@ -12,7 +11,8 @@ module.exports = [ expectedFilenameLength: 17, expectedChunkFilenameLength: 19 } - }, { + }, + { name: "hash in publicPath", output: { publicPath: "/[hash]/", @@ -23,7 +23,8 @@ module.exports = [ expectedFilenameLength: 31, expectedChunkFilenameLength: 33 } - }, { + }, + { name: "chunkhash with length", output: { filename: "bundle2.[chunkhash:8].js", @@ -33,7 +34,8 @@ module.exports = [ expectedFilenameLength: 19, expectedChunkFilenameLength: 21 } - }, { + }, + { name: "chunkhash", output: { filename: "bundle3.[chunkhash].js", @@ -43,7 +45,8 @@ module.exports = [ expectedFilenameLength: 31, expectedChunkFilenameLength: 33 } - }, { + }, + { name: "hash with and without length", output: { filename: "bundle4.[hash].js", @@ -53,7 +56,8 @@ module.exports = [ expectedFilenameLength: 31, expectedChunkFilenameLength: 21 } - }, { + }, + { name: "hash with length", output: { filename: "bundle5.[hash:6].js", @@ -63,7 +67,8 @@ module.exports = [ expectedFilenameLength: 17, expectedChunkFilenameLength: 21 } - }, { + }, + { name: "chunkhash in chunkFilename ", output: { filename: "bundle6.[hash].js", @@ -73,10 +78,9 @@ module.exports = [ expectedFilenameLength: 31, expectedChunkFilenameLength: 20 }, - plugins: [ - new webpack.HotModuleReplacementPlugin() - ] - }, { + plugins: [new webpack.HotModuleReplacementPlugin()] + }, + { name: "hash with length and chunkhash with length", output: { filename: "bundle7.[hash:7].js", @@ -87,12 +91,12 @@ module.exports = [ expectedFilenameLength: 18, expectedChunkFilenameLength: 20 } - }, { + }, + { name: "hash with length in chunkFilename", output: { filename: "bundle8.[hash].js", chunkFilename: "[id].bundle8.[hash:7].js" - }, target: "node", amd: { @@ -105,7 +109,6 @@ module.exports = [ output: { filename: "bundle9.[hash].js", chunkFilename: "[id].bundle9.[chunkhash:7].js" - }, target: "node", amd: { @@ -117,7 +120,9 @@ module.exports = [ module.exports.forEach(function(options) { options.plugins = options.plugins || []; - options.plugins.push(new webpack.DefinePlugin({ - NAME: JSON.stringify(options.name) - })); + options.plugins.push( + new webpack.DefinePlugin({ + NAME: JSON.stringify(options.name) + }) + ); }); diff --git a/test/configCases/ignore/only-resource-context/webpack.config.js b/test/configCases/ignore/only-resource-context/webpack.config.js index 9e6878ccf..d766ec024 100644 --- a/test/configCases/ignore/only-resource-context/webpack.config.js +++ b/test/configCases/ignore/only-resource-context/webpack.config.js @@ -4,7 +4,5 @@ const IgnorePlugin = require("../../../../lib/IgnorePlugin"); module.exports = { entry: "./test.js", - plugins: [ - new IgnorePlugin(/ignored-module/) - ], + plugins: [new IgnorePlugin(/ignored-module/)] }; diff --git a/test/configCases/ignore/only-resource/webpack.config.js b/test/configCases/ignore/only-resource/webpack.config.js index 9e6878ccf..d766ec024 100644 --- a/test/configCases/ignore/only-resource/webpack.config.js +++ b/test/configCases/ignore/only-resource/webpack.config.js @@ -4,7 +4,5 @@ const IgnorePlugin = require("../../../../lib/IgnorePlugin"); module.exports = { entry: "./test.js", - plugins: [ - new IgnorePlugin(/ignored-module/) - ], + plugins: [new IgnorePlugin(/ignored-module/)] }; diff --git a/test/configCases/ignore/resource-and-context-contextmodule/webpack.config.js b/test/configCases/ignore/resource-and-context-contextmodule/webpack.config.js index 21340131c..7151dfc88 100644 --- a/test/configCases/ignore/resource-and-context-contextmodule/webpack.config.js +++ b/test/configCases/ignore/resource-and-context-contextmodule/webpack.config.js @@ -4,7 +4,5 @@ const IgnorePlugin = require("../../../../lib/IgnorePlugin"); module.exports = { entry: "./test.js", - plugins: [ - new IgnorePlugin(/ignored-module/, /folder-b/) - ], + plugins: [new IgnorePlugin(/ignored-module/, /folder-b/)] }; diff --git a/test/configCases/ignore/resource-and-context/webpack.config.js b/test/configCases/ignore/resource-and-context/webpack.config.js index 21340131c..7151dfc88 100644 --- a/test/configCases/ignore/resource-and-context/webpack.config.js +++ b/test/configCases/ignore/resource-and-context/webpack.config.js @@ -4,7 +4,5 @@ const IgnorePlugin = require("../../../../lib/IgnorePlugin"); module.exports = { entry: "./test.js", - plugins: [ - new IgnorePlugin(/ignored-module/, /folder-b/) - ], + plugins: [new IgnorePlugin(/ignored-module/, /folder-b/)] }; diff --git a/test/configCases/library/0-create-library/webpack.config.js b/test/configCases/library/0-create-library/webpack.config.js index 3f2394e39..a2e200769 100644 --- a/test/configCases/library/0-create-library/webpack.config.js +++ b/test/configCases/library/0-create-library/webpack.config.js @@ -1,5 +1,4 @@ module.exports = [ - { output: { filename: "commonjs.js", diff --git a/test/configCases/library/1-use-library/webpack.config.js b/test/configCases/library/1-use-library/webpack.config.js index 9db411321..05624691f 100644 --- a/test/configCases/library/1-use-library/webpack.config.js +++ b/test/configCases/library/1-use-library/webpack.config.js @@ -1,11 +1,13 @@ var webpack = require("../../../../"); var path = require("path"); module.exports = [ - { resolve: { alias: { - library: path.resolve(__dirname, "../../../js/config/library/0-create-library/commonjs.js") + library: path.resolve( + __dirname, + "../../../js/config/library/0-create-library/commonjs.js" + ) } }, plugins: [ @@ -17,7 +19,10 @@ module.exports = [ { resolve: { alias: { - library: path.resolve(__dirname, "../../../js/config/library/0-create-library/umd.js") + library: path.resolve( + __dirname, + "../../../js/config/library/0-create-library/umd.js" + ) } }, plugins: [ @@ -30,7 +35,10 @@ module.exports = [ entry: "./global-test.js", resolve: { alias: { - library: path.resolve(__dirname, "../../../js/config/library/0-create-library/this.js") + library: path.resolve( + __dirname, + "../../../js/config/library/0-create-library/this.js" + ) } }, plugins: [ @@ -42,7 +50,10 @@ module.exports = [ { resolve: { alias: { - library: path.resolve(__dirname, "../../../js/config/library/0-create-library/commonjs2-external.js"), + library: path.resolve( + __dirname, + "../../../js/config/library/0-create-library/commonjs2-external.js" + ), external: path.resolve(__dirname, "node_modules/external.js") } }, @@ -57,7 +68,10 @@ module.exports = [ entry: "./default-test.js", resolve: { alias: { - library: path.resolve(__dirname, "../../../js/config/library/0-create-library/umd-default.js") + library: path.resolve( + __dirname, + "../../../js/config/library/0-create-library/umd-default.js" + ) } }, plugins: [ diff --git a/test/configCases/loaders/generate-ident/webpack.config.js b/test/configCases/loaders/generate-ident/webpack.config.js index f373fb94e..b52f63dab 100644 --- a/test/configCases/loaders/generate-ident/webpack.config.js +++ b/test/configCases/loaders/generate-ident/webpack.config.js @@ -1,7 +1,6 @@ module.exports = { module: { rules: [ - { test: /a\.js$/, use: [ @@ -18,9 +17,7 @@ module.exports = { }, { test: /(b|c)\.js$/, - use: [ - "./loader1" - ] + use: ["./loader1"] }, { test: /b\.js$/, diff --git a/test/configCases/loaders/hot-in-context/webpack.config.js b/test/configCases/loaders/hot-in-context/webpack.config.js index 2ddd7a833..925a31824 100644 --- a/test/configCases/loaders/hot-in-context/webpack.config.js +++ b/test/configCases/loaders/hot-in-context/webpack.config.js @@ -1,9 +1,10 @@ const webpack = require("../../../../"); -module.exports = [{ - // no hmr -}, { - // with hmr - plugins: [ - new webpack.HotModuleReplacementPlugin() - ] -}]; +module.exports = [ + { + // no hmr + }, + { + // with hmr + plugins: [new webpack.HotModuleReplacementPlugin()] + } +]; diff --git a/test/configCases/loaders/issue-3320/webpack.config.js b/test/configCases/loaders/issue-3320/webpack.config.js index d48327458..8617ad417 100644 --- a/test/configCases/loaders/issue-3320/webpack.config.js +++ b/test/configCases/loaders/issue-3320/webpack.config.js @@ -6,21 +6,24 @@ module.exports = { }, module: { rules: [ - { test: /a\.js$/, - use: [{ - loader: "some-loader" - }] + use: [ + { + loader: "some-loader" + } + ] }, { test: /b\.js$/, - use: [{ - loader: "some-loader", - options: { - foo: "someOtherMessage" + use: [ + { + loader: "some-loader", + options: { + foo: "someOtherMessage" + } } - }] + ] }, { test: /b2\.js$/, @@ -28,9 +31,7 @@ module.exports = { }, { test: /b3\.js$/, - use: [ - "some-loader?foo=someOtherMessage" - ] + use: ["some-loader?foo=someOtherMessage"] } ] } diff --git a/test/configCases/loaders/pre-post-loader/webpack.config.js b/test/configCases/loaders/pre-post-loader/webpack.config.js index f7a01fae3..5a229d44a 100644 --- a/test/configCases/loaders/pre-post-loader/webpack.config.js +++ b/test/configCases/loaders/pre-post-loader/webpack.config.js @@ -1,10 +1,9 @@ module.exports = { module: { rules: [ - { test: /a\.js$/, - use: "./loader1", + use: "./loader1" }, { test: /a\.js$/, diff --git a/test/configCases/loaders/remaining-request/webpack.config.js b/test/configCases/loaders/remaining-request/webpack.config.js index 688eab459..9119ae940 100644 --- a/test/configCases/loaders/remaining-request/webpack.config.js +++ b/test/configCases/loaders/remaining-request/webpack.config.js @@ -1,19 +1,21 @@ module.exports = { module: { - rules: [{ - test: /a\.js$/, - use: [ - "./loader1", - { - loader: "./loader2", - ident: "loader2", - options: { - f: function() { - return "ok"; + rules: [ + { + test: /a\.js$/, + use: [ + "./loader1", + { + loader: "./loader2", + ident: "loader2", + options: { + f: function() { + return "ok"; + } } } - } - ] - }] + ] + } + ] } }; diff --git a/test/configCases/output/function/webpack.config.js b/test/configCases/output/function/webpack.config.js index b1d8d59c5..2cfbedfe1 100644 --- a/test/configCases/output/function/webpack.config.js +++ b/test/configCases/output/function/webpack.config.js @@ -6,7 +6,7 @@ module.exports = { }; }, output: { - filename: (data) => { + filename: data => { return data.chunk.name === "a" ? `${data.chunk.name}.js` : "[name].js"; } } diff --git a/test/configCases/parsing/extended-api/webpack.config.js b/test/configCases/parsing/extended-api/webpack.config.js index be0b93bd5..3eeca328d 100644 --- a/test/configCases/parsing/extended-api/webpack.config.js +++ b/test/configCases/parsing/extended-api/webpack.config.js @@ -5,7 +5,5 @@ module.exports = { entry: { other: "./index" }, - plugins: [ - new webpack.ExtendedAPIPlugin() - ] + plugins: [new webpack.ExtendedAPIPlugin()] }; diff --git a/test/configCases/parsing/harmony-this-concat/webpack.config.js b/test/configCases/parsing/harmony-this-concat/webpack.config.js index 3b6df3666..9cd2bdf56 100644 --- a/test/configCases/parsing/harmony-this-concat/webpack.config.js +++ b/test/configCases/parsing/harmony-this-concat/webpack.config.js @@ -3,7 +3,5 @@ module.exports = { module: { strictThisContextOnImports: true }, - plugins: [ - new webpack.optimize.ModuleConcatenationPlugin() - ] + plugins: [new webpack.optimize.ModuleConcatenationPlugin()] }; diff --git a/test/configCases/parsing/system.import/webpack.config.js b/test/configCases/parsing/system.import/webpack.config.js index 7db7d8279..ae747d611 100644 --- a/test/configCases/parsing/system.import/webpack.config.js +++ b/test/configCases/parsing/system.import/webpack.config.js @@ -5,12 +5,14 @@ function createConfig(system) { return { name: `system_${systemString}`, module: { - rules: [{ - test: /\.js$/, - parser: { - system + rules: [ + { + test: /\.js$/, + parser: { + system + } } - }] + ] }, plugins: [ new webpack.DefinePlugin({ diff --git a/test/configCases/plugins/banner-plugin-hashing/webpack.config.js b/test/configCases/plugins/banner-plugin-hashing/webpack.config.js index 93ec0f03e..5c51d328b 100644 --- a/test/configCases/plugins/banner-plugin-hashing/webpack.config.js +++ b/test/configCases/plugins/banner-plugin-hashing/webpack.config.js @@ -16,7 +16,8 @@ module.exports = { }, plugins: [ new webpack.BannerPlugin({ - banner: "hash:[hash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]" + banner: + "hash:[hash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]" }) ] }; diff --git a/test/configCases/plugins/define-plugin/webpack.config.js b/test/configCases/plugins/define-plugin/webpack.config.js index 1f2609582..867ee3186 100644 --- a/test/configCases/plugins/define-plugin/webpack.config.js +++ b/test/configCases/plugins/define-plugin/webpack.config.js @@ -22,11 +22,11 @@ module.exports = { } }, "process.env.DEFINED_NESTED_KEY": 5, - "process.env.DEFINED_NESTED_KEY_STRING": "\"string\"", + "process.env.DEFINED_NESTED_KEY_STRING": '"string"', "typeof wurst": "typeof suppe", "typeof suppe": "typeof wurst", - "wurst": "suppe", - "suppe": "wurst", + wurst: "suppe", + suppe: "wurst" }) ] }; diff --git a/test/configCases/plugins/environment-plugin/webpack.config.js b/test/configCases/plugins/environment-plugin/webpack.config.js index f8f533d1c..aee27dae3 100644 --- a/test/configCases/plugins/environment-plugin/webpack.config.js +++ b/test/configCases/plugins/environment-plugin/webpack.config.js @@ -10,61 +10,58 @@ process.env.FFF = "fff"; process.env.GGG = "ggg"; process.env.III = ""; -module.exports = [{ - name: "aaa", - module: { - unknownContextRegExp: /$^/, - unknownContextCritical: false +module.exports = [ + { + name: "aaa", + module: { + unknownContextRegExp: /$^/, + unknownContextCritical: false + }, + plugins: [new EnvironmentPlugin("AAA")] }, - plugins: [ - new EnvironmentPlugin("AAA") - ] -}, { - name: "bbbccc", - module: { - unknownContextRegExp: /$^/, - unknownContextCritical: false + { + name: "bbbccc", + module: { + unknownContextRegExp: /$^/, + unknownContextCritical: false + }, + plugins: [new EnvironmentPlugin("BBB", "CCC")] }, - plugins: [ - new EnvironmentPlugin("BBB", "CCC") - ] -}, { - name: "ddd", - module: { - unknownContextRegExp: /$^/, - unknownContextCritical: false + { + name: "ddd", + module: { + unknownContextRegExp: /$^/, + unknownContextCritical: false + }, + plugins: [new EnvironmentPlugin("DDD")] }, - plugins: [ - new EnvironmentPlugin("DDD") - ] -}, { - name: "eeefff", - module: { - unknownContextRegExp: /$^/, - unknownContextCritical: false + { + name: "eeefff", + module: { + unknownContextRegExp: /$^/, + unknownContextCritical: false + }, + plugins: [new EnvironmentPlugin(["EEE", "FFF"])] }, - plugins: [ - new EnvironmentPlugin(["EEE", "FFF"]) - ] -}, { - name: "ggghhh", - module: { - unknownContextRegExp: /$^/, - unknownContextCritical: false + { + name: "ggghhh", + module: { + unknownContextRegExp: /$^/, + unknownContextCritical: false + }, + plugins: [ + new EnvironmentPlugin({ + GGG: "ggg-default", + HHH: "hhh" + }) + ] }, - plugins: [ - new EnvironmentPlugin({ - GGG: "ggg-default", - HHH: "hhh" - }) - ] -}, { - name: "iii", - module: { - unknownContextRegExp: /$^/, - unknownContextCritical: false - }, - plugins: [ - new EnvironmentPlugin("III") - ] -}]; + { + name: "iii", + module: { + unknownContextRegExp: /$^/, + unknownContextCritical: false + }, + plugins: [new EnvironmentPlugin("III")] + } +]; diff --git a/test/configCases/plugins/lib-manifest-plugin/webpack.config.js b/test/configCases/plugins/lib-manifest-plugin/webpack.config.js index af95723de..2b9b7fc2b 100644 --- a/test/configCases/plugins/lib-manifest-plugin/webpack.config.js +++ b/test/configCases/plugins/lib-manifest-plugin/webpack.config.js @@ -7,7 +7,10 @@ module.exports = { }, plugins: [ new LibManifestPlugin({ - path: path.resolve(__dirname, "../../../js/config/plugins/lib-manifest-plugin/[name]-manifest.json"), + path: path.resolve( + __dirname, + "../../../js/config/plugins/lib-manifest-plugin/[name]-manifest.json" + ), name: "[name]_[hash]" }) ], diff --git a/test/configCases/plugins/progress-plugin/webpack.config.js b/test/configCases/plugins/progress-plugin/webpack.config.js index a1bf26cb2..baeba1971 100644 --- a/test/configCases/plugins/progress-plugin/webpack.config.js +++ b/test/configCases/plugins/progress-plugin/webpack.config.js @@ -9,14 +9,17 @@ module.exports = { data.push(messages.join("|")); }), { - apply: (compiler) => { + apply: compiler => { compiler.hooks.compilation.tap("CustomPlugin", compilation => { - compilation.hooks.optimize.tap({ - name: "CustomPlugin", - context: true - }, (context) => { - context.reportProgress(0, "custom category", "custom message"); - }); + compilation.hooks.optimize.tap( + { + name: "CustomPlugin", + context: true + }, + context => { + context.reportProgress(0, "custom category", "custom message"); + } + ); }); } } diff --git a/test/configCases/plugins/provide-plugin/webpack.config.js b/test/configCases/plugins/provide-plugin/webpack.config.js index 385e6bffd..cba942cab 100644 --- a/test/configCases/plugins/provide-plugin/webpack.config.js +++ b/test/configCases/plugins/provide-plugin/webpack.config.js @@ -4,12 +4,12 @@ module.exports = { new ProvidePlugin({ aaa: "./aaa", "bbb.ccc": "./bbbccc", - "dddeeefff": ["./ddd", "eee", "3-f"], + dddeeefff: ["./ddd", "eee", "3-f"], "process.env.NODE_ENV": "./env", es2015: "./harmony", es2015_name: ["./harmony", "default"], es2015_alias: ["./harmony", "alias"], - es2015_year: ["./harmony", "year"], + es2015_year: ["./harmony", "year"] }) ] }; diff --git a/test/configCases/plugins/source-map-dev-tool-plugin/webpack.config.js b/test/configCases/plugins/source-map-dev-tool-plugin/webpack.config.js index 8e33aaeeb..1943817ed 100644 --- a/test/configCases/plugins/source-map-dev-tool-plugin/webpack.config.js +++ b/test/configCases/plugins/source-map-dev-tool-plugin/webpack.config.js @@ -6,8 +6,8 @@ module.exports = { __filename: false }, entry: { - "bundle0": ["./index.js"], - "public/test": ["./test.js"], + bundle0: ["./index.js"], + "public/test": ["./test.js"] }, output: { filename: "[name].js" diff --git a/test/configCases/plugins/uglifyjs-plugin/webpack.config.js b/test/configCases/plugins/uglifyjs-plugin/webpack.config.js index 03bb26bc9..b8f7ec167 100644 --- a/test/configCases/plugins/uglifyjs-plugin/webpack.config.js +++ b/test/configCases/plugins/uglifyjs-plugin/webpack.config.js @@ -18,16 +18,11 @@ module.exports = { minimize: true, minimizer: [ new UglifyJsPlugin({ - exclude: [ - "vendors.js", - "extract.js" - ] + exclude: ["vendors.js", "extract.js"] }), new UglifyJsPlugin({ extractComments: true, - include: [ - "extract.js" - ] + include: ["extract.js"] }), new UglifyJsPlugin({ uglifyOptions: { @@ -35,9 +30,7 @@ module.exports = { passes: 2 } }, - include: [ - "compress.js" - ] + include: ["compress.js"] }) ] } diff --git a/test/configCases/records/issue-295/webpack.config.js b/test/configCases/records/issue-295/webpack.config.js index 777300024..987f3640b 100644 --- a/test/configCases/records/issue-295/webpack.config.js +++ b/test/configCases/records/issue-295/webpack.config.js @@ -2,7 +2,10 @@ var path = require("path"); module.exports = { entry: "./test", - recordsPath: path.resolve(__dirname, "../../../js/config/records/issue-295/records.json"), + recordsPath: path.resolve( + __dirname, + "../../../js/config/records/issue-295/records.json" + ), target: "node", node: { __dirname: false diff --git a/test/configCases/records/issue-2991/webpack.config.js b/test/configCases/records/issue-2991/webpack.config.js index 89b7799a3..3d017931f 100644 --- a/test/configCases/records/issue-2991/webpack.config.js +++ b/test/configCases/records/issue-2991/webpack.config.js @@ -2,7 +2,10 @@ var path = require("path"); module.exports = { entry: "./test", - recordsOutputPath: path.resolve(__dirname, "../../../js/config/records/issue-2991/records.json"), + recordsOutputPath: path.resolve( + __dirname, + "../../../js/config/records/issue-2991/records.json" + ), target: "node", node: { __dirname: false diff --git a/test/configCases/rule-set/chaining/webpack.config.js b/test/configCases/rule-set/chaining/webpack.config.js index 5eaf9e083..65b6f40e5 100644 --- a/test/configCases/rule-set/chaining/webpack.config.js +++ b/test/configCases/rule-set/chaining/webpack.config.js @@ -1,7 +1,6 @@ module.exports = { module: { rules: [ - { resource: /abc\.js$/, loader: "./loader?a!./loader?b" diff --git a/test/configCases/rule-set/compiler/webpack.config.js b/test/configCases/rule-set/compiler/webpack.config.js index d212414a5..3b42db9b0 100644 --- a/test/configCases/rule-set/compiler/webpack.config.js +++ b/test/configCases/rule-set/compiler/webpack.config.js @@ -2,7 +2,6 @@ module.exports = { name: "compiler-name", module: { rules: [ - { test: /a\.js$/, compiler: "compiler", diff --git a/test/configCases/rule-set/custom/webpack.config.js b/test/configCases/rule-set/custom/webpack.config.js index 3f7eddfcb..916008971 100644 --- a/test/configCases/rule-set/custom/webpack.config.js +++ b/test/configCases/rule-set/custom/webpack.config.js @@ -1,17 +1,19 @@ module.exports = { module: { - rules: [{ - test: /[ab]\.js$/, - use: function(data) { - return { - loader: "./loader", - options: { - resource: data.resource.replace(/^.*[\\/]/g, ""), - resourceQuery: data.resourceQuery, - issuer: data.issuer.replace(/^.*[\\/]/g, ""), - } - }; + rules: [ + { + test: /[ab]\.js$/, + use: function(data) { + return { + loader: "./loader", + options: { + resource: data.resource.replace(/^.*[\\/]/g, ""), + resourceQuery: data.resourceQuery, + issuer: data.issuer.replace(/^.*[\\/]/g, "") + } + }; + } } - }] + ] } }; diff --git a/test/configCases/rule-set/query/webpack.config.js b/test/configCases/rule-set/query/webpack.config.js index c2e46d510..cfa3e696e 100644 --- a/test/configCases/rule-set/query/webpack.config.js +++ b/test/configCases/rule-set/query/webpack.config.js @@ -1,8 +1,10 @@ module.exports = { module: { - rules: [{ - resourceQuery: /^\?loader/, - use: "./loader?query" - }] + rules: [ + { + resourceQuery: /^\?loader/, + use: "./loader?query" + } + ] } }; diff --git a/test/configCases/rule-set/resolve-options/webpack.config.js b/test/configCases/rule-set/resolve-options/webpack.config.js index c62b13304..9ce4b7957 100644 --- a/test/configCases/rule-set/resolve-options/webpack.config.js +++ b/test/configCases/rule-set/resolve-options/webpack.config.js @@ -1,12 +1,14 @@ module.exports = { module: { - rules: [{ - test: require.resolve("./a"), - resolve: { - alias: { - "./wrong": "./ok" + rules: [ + { + test: require.resolve("./a"), + resolve: { + alias: { + "./wrong": "./ok" + } } } - }] + ] } }; diff --git a/test/configCases/rule-set/simple-use-array-fn/webpack.config.js b/test/configCases/rule-set/simple-use-array-fn/webpack.config.js index 4273a7009..f16f3585d 100644 --- a/test/configCases/rule-set/simple-use-array-fn/webpack.config.js +++ b/test/configCases/rule-set/simple-use-array-fn/webpack.config.js @@ -1,48 +1,42 @@ module.exports = { module: { - rules: [{ - oneOf: [{ - test: { - and: [ - /a.\.js$/, - /b\.js$/ - ] - }, - loader: "./loader?first" - }, - { - test: [ - require.resolve("./a"), - require.resolve("./c"), - ], - issuer: require.resolve("./b"), - use: data => ([ - "./loader?second-1", - { - loader: "./loader", - options: "second-2" + rules: [ + { + oneOf: [ + { + test: { + and: [/a.\.js$/, /b\.js$/] }, - { - loader: "./loader", - options: { - get: function() { - return "second-3"; + loader: "./loader?first" + }, + { + test: [require.resolve("./a"), require.resolve("./c")], + issuer: require.resolve("./b"), + use: data => [ + "./loader?second-1", + { + loader: "./loader", + options: "second-2" + }, + { + loader: "./loader", + options: { + get: function() { + return "second-3"; + } } } - } - ]) - }, - { - test: { - or: [ - require.resolve("./a"), - require.resolve("./c"), ] }, - loader: "./loader", - options: "third" - } - ] - }] + { + test: { + or: [require.resolve("./a"), require.resolve("./c")] + }, + loader: "./loader", + options: "third" + } + ] + } + ] } }; diff --git a/test/configCases/rule-set/simple-use-fn-array/webpack.config.js b/test/configCases/rule-set/simple-use-fn-array/webpack.config.js index 74adf017b..15d939bfb 100644 --- a/test/configCases/rule-set/simple-use-fn-array/webpack.config.js +++ b/test/configCases/rule-set/simple-use-fn-array/webpack.config.js @@ -24,35 +24,29 @@ var useArray = createFunctionArrayFromUseArray([ module.exports = { module: { - rules: [{ - oneOf: [{ - test: { - and: [ - /a.\.js$/, - /b\.js$/ - ] + rules: [ + { + oneOf: [ + { + test: { + and: [/a.\.js$/, /b\.js$/] + }, + loader: "./loader?first" }, - loader: "./loader?first" - }, - { - test: [ - require.resolve("./a"), - require.resolve("./c"), - ], - issuer: require.resolve("./b"), - use: useArray - }, - { - test: { - or: [ - require.resolve("./a"), - require.resolve("./c"), - ] + { + test: [require.resolve("./a"), require.resolve("./c")], + issuer: require.resolve("./b"), + use: useArray }, - loader: "./loader", - options: "third" - } - ] - }] + { + test: { + or: [require.resolve("./a"), require.resolve("./c")] + }, + loader: "./loader", + options: "third" + } + ] + } + ] } }; diff --git a/test/configCases/rule-set/simple/webpack.config.js b/test/configCases/rule-set/simple/webpack.config.js index 4e22e031b..b981f42a0 100644 --- a/test/configCases/rule-set/simple/webpack.config.js +++ b/test/configCases/rule-set/simple/webpack.config.js @@ -1,48 +1,42 @@ module.exports = { module: { - rules: [{ - oneOf: [{ - test: { - and: [ - /a.\.js$/, - /b\.js$/ - ] - }, - loader: "./loader?first" - }, - { - test: [ - require.resolve("./a"), - require.resolve("./c"), - ], - issuer: require.resolve("./b"), - use: [ - "./loader?second-1", - { - loader: "./loader", - options: "second-2" + rules: [ + { + oneOf: [ + { + test: { + and: [/a.\.js$/, /b\.js$/] }, - { - loader: "./loader", - options: { - get: function() { - return "second-3"; + loader: "./loader?first" + }, + { + test: [require.resolve("./a"), require.resolve("./c")], + issuer: require.resolve("./b"), + use: [ + "./loader?second-1", + { + loader: "./loader", + options: "second-2" + }, + { + loader: "./loader", + options: { + get: function() { + return "second-3"; + } } } - } - ] - }, - { - test: { - or: [ - require.resolve("./a"), - require.resolve("./c"), ] }, - loader: "./loader", - options: "third" - } - ] - }] + { + test: { + or: [require.resolve("./a"), require.resolve("./c")] + }, + loader: "./loader", + options: "third" + } + ] + } + ] } }; diff --git a/test/configCases/scope-hoisting/create-dll-plugin/webpack.config.js b/test/configCases/scope-hoisting/create-dll-plugin/webpack.config.js index f6a7ae1a0..f169ea12e 100644 --- a/test/configCases/scope-hoisting/create-dll-plugin/webpack.config.js +++ b/test/configCases/scope-hoisting/create-dll-plugin/webpack.config.js @@ -4,7 +4,10 @@ module.exports = { entry: ["./index.js"], plugins: [ new webpack.DllPlugin({ - path: path.resolve(__dirname, "../../../js/config/scope-hoisting/create-dll-plugin/manifest.json") + path: path.resolve( + __dirname, + "../../../js/config/scope-hoisting/create-dll-plugin/manifest.json" + ) }), new webpack.optimize.ModuleConcatenationPlugin() ] diff --git a/test/configCases/scope-hoisting/dll-plugin/webpack.config.js b/test/configCases/scope-hoisting/dll-plugin/webpack.config.js index 76b20113e..14a6d08cc 100644 --- a/test/configCases/scope-hoisting/dll-plugin/webpack.config.js +++ b/test/configCases/scope-hoisting/dll-plugin/webpack.config.js @@ -10,7 +10,7 @@ module.exports = { buildMeta: { exportsType: "namespace", providedExports: ["default"] - }, + } } } }), diff --git a/test/configCases/scope-hoisting/strictThisContextOnImports/webpack.config.js b/test/configCases/scope-hoisting/strictThisContextOnImports/webpack.config.js index 3b6df3666..9cd2bdf56 100644 --- a/test/configCases/scope-hoisting/strictThisContextOnImports/webpack.config.js +++ b/test/configCases/scope-hoisting/strictThisContextOnImports/webpack.config.js @@ -3,7 +3,5 @@ module.exports = { module: { strictThisContextOnImports: true }, - plugins: [ - new webpack.optimize.ModuleConcatenationPlugin() - ] + plugins: [new webpack.optimize.ModuleConcatenationPlugin()] }; diff --git a/test/configCases/side-effects/side-effects-override/webpack.config.js b/test/configCases/side-effects/side-effects-override/webpack.config.js index ab65d3174..789ad53cf 100644 --- a/test/configCases/side-effects/side-effects-override/webpack.config.js +++ b/test/configCases/side-effects/side-effects-override/webpack.config.js @@ -2,7 +2,8 @@ const path = require("path"); module.exports = { mode: "production", module: { - rules: [{ + rules: [ + { test: path.resolve(__dirname, "node_modules/pmodule"), sideEffects: true }, diff --git a/test/configCases/simple/empty-config/webpack.config.js b/test/configCases/simple/empty-config/webpack.config.js index f4d625303..f053ebf79 100644 --- a/test/configCases/simple/empty-config/webpack.config.js +++ b/test/configCases/simple/empty-config/webpack.config.js @@ -1,3 +1 @@ -module.exports = { - -}; +module.exports = {}; diff --git a/test/configCases/simple/multi-compiler/webpack.config.js b/test/configCases/simple/multi-compiler/webpack.config.js index dc4535743..c5578074b 100644 --- a/test/configCases/simple/multi-compiler/webpack.config.js +++ b/test/configCases/simple/multi-compiler/webpack.config.js @@ -1,3 +1 @@ -module.exports = [{ - -}]; +module.exports = [{}]; diff --git a/test/configCases/source-map/nosources/webpack.config.js b/test/configCases/source-map/nosources/webpack.config.js index 0b1750b1b..07b6b6160 100644 --- a/test/configCases/source-map/nosources/webpack.config.js +++ b/test/configCases/source-map/nosources/webpack.config.js @@ -4,5 +4,5 @@ module.exports = { __dirname: false, __filename: false }, - devtool: "nosources-source-map", + devtool: "nosources-source-map" }; diff --git a/test/configCases/source-map/source-map-filename-contenthash/webpack.config.js b/test/configCases/source-map/source-map-filename-contenthash/webpack.config.js index 7ada888d9..01478ecd9 100644 --- a/test/configCases/source-map/source-map-filename-contenthash/webpack.config.js +++ b/test/configCases/source-map/source-map-filename-contenthash/webpack.config.js @@ -6,6 +6,6 @@ module.exports = { }, devtool: "source-map", output: { - sourceMapFilename: "[file]-[contenthash].map?[contenthash]-[contenthash]", + sourceMapFilename: "[file]-[contenthash].map?[contenthash]-[contenthash]" } }; diff --git a/test/configCases/target/buffer-default/webpack.config.js b/test/configCases/target/buffer-default/webpack.config.js index 20f2621b1..7105dc09e 100644 --- a/test/configCases/target/buffer-default/webpack.config.js +++ b/test/configCases/target/buffer-default/webpack.config.js @@ -1,3 +1,3 @@ module.exports = { - target: "web", + target: "web" }; diff --git a/test/formatLocation.unittest.js b/test/formatLocation.unittest.js index 6fe04edf8..5cebdb405 100644 --- a/test/formatLocation.unittest.js +++ b/test/formatLocation.unittest.js @@ -4,90 +4,102 @@ require("should"); const formatLocation = require("../lib/formatLocation"); describe("formatLocation", () => { - const testCases = [{ - name: "undefined", - loc: undefined, - result: "" - }, { - name: "null", - loc: null, - result: "" - }, { - name: "string", - loc: "str", - result: "str" - }, { - name: "number", - loc: 12, - result: "12" - }, { - name: "line-column", - loc: { - start: { - line: 1, - column: 2 + const testCases = [ + { + name: "undefined", + loc: undefined, + result: "" + }, + { + name: "null", + loc: null, + result: "" + }, + { + name: "string", + loc: "str", + result: "str" + }, + { + name: "number", + loc: 12, + result: "12" + }, + { + name: "line-column", + loc: { + start: { + line: 1, + column: 2 + }, + end: { + line: 3, + column: 4 + } }, - end: { - line: 3, - column: 4 - } + result: "1:2-3:4" }, - result: "1:2-3:4" - }, { - name: "line-column (same line)", - loc: { - start: { - line: 1, - column: 2 + { + name: "line-column (same line)", + loc: { + start: { + line: 1, + column: 2 + }, + end: { + line: 1, + column: 4 + } }, - end: { - line: 1, - column: 4 - } + result: "1:2-4" }, - result: "1:2-4" - }, { - name: "line-column (start only)", - loc: { - start: { - line: 5, - column: 6 - } - }, - result: "5:6" - }, { - name: "start-end string", - loc: { - start: "start", - end: "end" - }, - result: "start-end" - }, { - name: "start-end number", - loc: { - start: 9, - end: 7 - }, - result: "9-7" - }, { - name: "line", - loc: { - start: { - line: 10 + { + name: "line-column (start only)", + loc: { + start: { + line: 5, + column: 6 + } }, - end: { - index: 20 - } + result: "5:6" }, - result: "10:?-+20" - }, { - name: "line", - loc: { - start: null, - end: /f/ + { + name: "start-end string", + loc: { + start: "start", + end: "end" + }, + result: "start-end" }, - result: "" - }]; + { + name: "start-end number", + loc: { + start: 9, + end: 7 + }, + result: "9-7" + }, + { + name: "line", + loc: { + start: { + line: 10 + }, + end: { + index: 20 + } + }, + result: "10:?-+20" + }, + { + name: "line", + loc: { + start: null, + end: /f/ + }, + result: "" + } + ]; testCases.forEach(testCase => { it(`should format location correctly for ${testCase.name}`, () => { formatLocation(testCase.loc).should.be.eql(testCase.result); diff --git a/test/hotCases/concat/reload-external/webpack.config.js b/test/hotCases/concat/reload-external/webpack.config.js index 9caf91ade..af45fdab5 100644 --- a/test/hotCases/concat/reload-external/webpack.config.js +++ b/test/hotCases/concat/reload-external/webpack.config.js @@ -3,7 +3,5 @@ const webpack = require("../../../../"); module.exports = { - plugins: [ - new webpack.optimize.ModuleConcatenationPlugin() - ] + plugins: [new webpack.optimize.ModuleConcatenationPlugin()] }; diff --git a/test/hotPlayground/webpack.config.js b/test/hotPlayground/webpack.config.js index cd0c477ce..0b5093d46 100644 --- a/test/hotPlayground/webpack.config.js +++ b/test/hotPlayground/webpack.config.js @@ -6,8 +6,6 @@ module.exports = { hotUpdateChunkFilename: "[id].[hash].bundle-update.js", hashDigestLength: 4 }, - plugins: [ - new webpack.HotModuleReplacementPlugin() - ], + plugins: [new webpack.HotModuleReplacementPlugin()], recordsPath: __dirname + "/records.json" // this is not required for the webpack-dev-server, but when compiled. }; diff --git a/test/identifier.unittest.js b/test/identifier.unittest.js index 6a2b15c3d..9c2134774 100644 --- a/test/identifier.unittest.js +++ b/test/identifier.unittest.js @@ -16,7 +16,9 @@ describe("util/identifier", () => { }); it("computes the correct relative results for the path construct", () => { - should(identifierUtil.makePathsRelative(context, pathConstruct)).be.exactly(expected); + should( + identifierUtil.makePathsRelative(context, pathConstruct) + ).be.exactly(expected); }); }); }); diff --git a/test/statsCases/async-commons-chunk-auto/webpack.config.js b/test/statsCases/async-commons-chunk-auto/webpack.config.js index 11bed473a..ecf8df0e7 100644 --- a/test/statsCases/async-commons-chunk-auto/webpack.config.js +++ b/test/statsCases/async-commons-chunk-auto/webpack.config.js @@ -10,7 +10,6 @@ const stats = { modules: false }; module.exports = [ - { name: "disabled", mode: "production", @@ -92,14 +91,15 @@ module.exports = [ minSize: 0, // enforce all chunks: "all", cacheGroups: { - "libs": module => { - if(!module.nameForCondition) return; + libs: module => { + if (!module.nameForCondition) return; const name = module.nameForCondition(); const match = /[\\/](xyz|x)\.js/.exec(name); - if(match) return { - name: "libs-" + match[1], - enforce: true - }; + if (match) + return { + name: "libs-" + match[1], + enforce: true + }; }, vendors: path.resolve(__dirname, "node_modules") } @@ -130,5 +130,4 @@ module.exports = [ }, stats } - ]; diff --git a/test/statsCases/commons-plugin-issue-4980/webpack.config.js b/test/statsCases/commons-plugin-issue-4980/webpack.config.js index a3881a5f6..ae2b553f5 100644 --- a/test/statsCases/commons-plugin-issue-4980/webpack.config.js +++ b/test/statsCases/commons-plugin-issue-4980/webpack.config.js @@ -1,44 +1,47 @@ // should generate vendor chunk with the same chunkhash for both entries -module.exports = [{ - mode: "production", - output: { - chunkFilename: "[name].[chunkhash].js" - }, - entry: { - app: "./entry-1.js" - }, - optimization: { - splitChunks: { - cacheGroups: { - vendor: { - name: "vendor", - chunks: "initial", - enforce: true, - test: /constants/ - } - } +module.exports = [ + { + mode: "production", + output: { + chunkFilename: "[name].[chunkhash].js" }, - namedModules: true - } -}, { - mode: "production", - output: { - chunkFilename: "[name].[chunkhash].js" - }, - entry: { - app: "./entry-2.js" - }, - optimization: { - splitChunks: { - cacheGroups: { - vendor: { - name: "vendor", - chunks: "initial", - enforce: true, - test: /constants/ - } - } + entry: { + app: "./entry-1.js" }, - namedModules: true + optimization: { + splitChunks: { + cacheGroups: { + vendor: { + name: "vendor", + chunks: "initial", + enforce: true, + test: /constants/ + } + } + }, + namedModules: true + } + }, + { + mode: "production", + output: { + chunkFilename: "[name].[chunkhash].js" + }, + entry: { + app: "./entry-2.js" + }, + optimization: { + splitChunks: { + cacheGroups: { + vendor: { + name: "vendor", + chunks: "initial", + enforce: true, + test: /constants/ + } + } + }, + namedModules: true + } } -}]; +]; diff --git a/test/statsCases/define-plugin/webpack.config.js b/test/statsCases/define-plugin/webpack.config.js index d0b10fc3d..999dc282d 100644 --- a/test/statsCases/define-plugin/webpack.config.js +++ b/test/statsCases/define-plugin/webpack.config.js @@ -1,6 +1,5 @@ var webpack = require("../../../"); module.exports = [ - { mode: "production", entry: "./index", @@ -20,5 +19,4 @@ module.exports = [ }) ] } - ]; diff --git a/test/statsCases/exclude-with-loader/webpack.config.js b/test/statsCases/exclude-with-loader/webpack.config.js index 7c90ee38d..46ce565d5 100644 --- a/test/statsCases/exclude-with-loader/webpack.config.js +++ b/test/statsCases/exclude-with-loader/webpack.config.js @@ -5,22 +5,20 @@ module.exports = { filename: "bundle.js" }, stats: { - excludeModules: [ - "node_modules", - "exclude" - ], - excludeAssets: [ - /\.json/ - ] + excludeModules: ["node_modules", "exclude"], + excludeAssets: [/\.json/] }, module: { - rules: [{ - test: /\.txt/, - loader: "raw-loader" - }, { - test: /\.json/, - loader: "file-loader", - type: "javascript/auto" - }] + rules: [ + { + test: /\.txt/, + loader: "raw-loader" + }, + { + test: /\.json/, + loader: "file-loader", + type: "javascript/auto" + } + ] } }; diff --git a/test/statsCases/filter-warnings/webpack.config.js b/test/statsCases/filter-warnings/webpack.config.js index bfd454a4f..aad74a388 100644 --- a/test/statsCases/filter-warnings/webpack.config.js +++ b/test/statsCases/filter-warnings/webpack.config.js @@ -12,7 +12,7 @@ const baseConfig = { sourceMap: true, uglifyOptions: { compress: { - warnings: true, + warnings: true }, mangle: false, output: { @@ -28,7 +28,7 @@ const baseConfig = { chunkModules: false, modules: false, providedExports: false, - usedExports: false, + usedExports: false } }; @@ -36,20 +36,20 @@ module.exports = [ undefined, "UglifyJs", /UglifyJs/, - warnings => true, ["UglifyJs"], + warnings => true, + ["UglifyJs"], [/UglifyJs/], - [ - warnings => true - ], + [warnings => true], "should not filter", /should not filter/, - warnings => false, ["should not filter"], + warnings => false, + ["should not filter"], [/should not filter/], - [ - warnings => false - ] -].map(filter => Object.assign({}, baseConfig, { - stats: Object.assign({}, baseConfig.stats, { - warningsFilter: filter + [warnings => false] +].map(filter => + Object.assign({}, baseConfig, { + stats: Object.assign({}, baseConfig.stats, { + warningsFilter: filter + }) }) -})); +); diff --git a/test/statsCases/import-context-filter/webpack.config.js b/test/statsCases/import-context-filter/webpack.config.js index 17a8cb689..070e43028 100644 --- a/test/statsCases/import-context-filter/webpack.config.js +++ b/test/statsCases/import-context-filter/webpack.config.js @@ -1,6 +1,6 @@ module.exports = { mode: "production", entry: { - "entry": "./entry", + entry: "./entry" } }; diff --git a/test/statsCases/import-weak/webpack.config.js b/test/statsCases/import-weak/webpack.config.js index 17a8cb689..070e43028 100644 --- a/test/statsCases/import-weak/webpack.config.js +++ b/test/statsCases/import-weak/webpack.config.js @@ -1,6 +1,6 @@ module.exports = { mode: "production", entry: { - "entry": "./entry", + entry: "./entry" } }; diff --git a/test/statsCases/named-chunks-plugin-async/webpack.config.js b/test/statsCases/named-chunks-plugin-async/webpack.config.js index 2df2a1ef9..ed9ebafae 100644 --- a/test/statsCases/named-chunks-plugin-async/webpack.config.js +++ b/test/statsCases/named-chunks-plugin-async/webpack.config.js @@ -6,23 +6,24 @@ const RequestShortener = require("../../../lib/RequestShortener"); module.exports = { mode: "production", entry: { - "entry": "./entry", + entry: "./entry" }, plugins: [ new NamedChunksPlugin(function(chunk) { - if(chunk.name) { + if (chunk.name) { return chunk.name; } - const chunkModulesToName = (chunk) => Array.from(chunk.modulesIterable, (mod) => { - const rs = new RequestShortener(mod.context); - return rs.shorten(mod.request).replace(/[./\\]/g, "_"); - }).join("-"); + const chunkModulesToName = chunk => + Array.from(chunk.modulesIterable, mod => { + const rs = new RequestShortener(mod.context); + return rs.shorten(mod.request).replace(/[./\\]/g, "_"); + }).join("-"); - if(chunk.getNumberOfModules() > 0) { + if (chunk.getNumberOfModules() > 0) { return `chunk-containing-${chunkModulesToName(chunk)}`; } return null; - }), + }) ] }; diff --git a/test/statsCases/named-chunks-plugin/webpack.config.js b/test/statsCases/named-chunks-plugin/webpack.config.js index 464ad2589..52fd02648 100644 --- a/test/statsCases/named-chunks-plugin/webpack.config.js +++ b/test/statsCases/named-chunks-plugin/webpack.config.js @@ -4,7 +4,7 @@ var NamedModulesPlugin = require("../../../lib/NamedModulesPlugin"); module.exports = { mode: "production", entry: { - "entry": "./entry" + entry: "./entry" }, optimization: { splitChunks: { @@ -18,8 +18,5 @@ module.exports = { } } }, - plugins: [ - new NamedChunksPlugin(), - new NamedModulesPlugin(), - ] + plugins: [new NamedChunksPlugin(), new NamedModulesPlugin()] }; diff --git a/test/statsCases/preset-mixed-array/webpack.config.js b/test/statsCases/preset-mixed-array/webpack.config.js index 937dffe6d..4b2a99a83 100644 --- a/test/statsCases/preset-mixed-array/webpack.config.js +++ b/test/statsCases/preset-mixed-array/webpack.config.js @@ -1,5 +1,4 @@ module.exports = [ - { name: "minimal", mode: "production", @@ -27,5 +26,4 @@ module.exports = [ assets: false } } - ]; diff --git a/test/statsCases/preset-none-array/webpack.config.js b/test/statsCases/preset-none-array/webpack.config.js index 83e152b4d..642b90fd4 100644 --- a/test/statsCases/preset-none-array/webpack.config.js +++ b/test/statsCases/preset-none-array/webpack.config.js @@ -1,5 +1,4 @@ module.exports = [ - { mode: "production", entry: "./index", @@ -11,5 +10,4 @@ module.exports = [ entry: "./index", stats: "none" } - ]; diff --git a/test/statsCases/resolve-plugin-context/webpack.config.js b/test/statsCases/resolve-plugin-context/webpack.config.js index c2d801035..5d7be1fe4 100644 --- a/test/statsCases/resolve-plugin-context/webpack.config.js +++ b/test/statsCases/resolve-plugin-context/webpack.config.js @@ -7,12 +7,10 @@ module.exports = { filename: "bundle.js" }, resolve: { - plugins: [ - new ResolvePackageFromRootPlugin(__dirname) - ] + plugins: [new ResolvePackageFromRootPlugin(__dirname)] }, stats: { chunkModules: false, - modules: true, + modules: true } }; diff --git a/test/statsCases/reverse-sort-modules/webpack.config.js b/test/statsCases/reverse-sort-modules/webpack.config.js index 0c1a904b9..f1f2620ec 100644 --- a/test/statsCases/reverse-sort-modules/webpack.config.js +++ b/test/statsCases/reverse-sort-modules/webpack.config.js @@ -4,6 +4,6 @@ module.exports = { performance: false, stats: { maxModules: 20, - modulesSort: "!id", + modulesSort: "!id" } }; diff --git a/test/statsCases/scope-hoisting-multi/webpack.config.js b/test/statsCases/scope-hoisting-multi/webpack.config.js index c7e8ec107..168d64fc2 100644 --- a/test/statsCases/scope-hoisting-multi/webpack.config.js +++ b/test/statsCases/scope-hoisting-multi/webpack.config.js @@ -1,5 +1,4 @@ module.exports = [ - { mode: "production", entry: { @@ -55,5 +54,4 @@ module.exports = [ optimizationBailout: true } } - ]; diff --git a/test/statsCases/simple-more-info/webpack.config.js b/test/statsCases/simple-more-info/webpack.config.js index 6b5ab815e..3ac8e8d8b 100644 --- a/test/statsCases/simple-more-info/webpack.config.js +++ b/test/statsCases/simple-more-info/webpack.config.js @@ -15,6 +15,6 @@ module.exports = { source: true, errorDetails: true, publicPath: true, - outputPath: true, + outputPath: true } }; diff --git a/test/statsCases/split-chunks-prefer-bigger-splits/webpack.config.js b/test/statsCases/split-chunks-prefer-bigger-splits/webpack.config.js index bbf3daaf4..273736e26 100644 --- a/test/statsCases/split-chunks-prefer-bigger-splits/webpack.config.js +++ b/test/statsCases/split-chunks-prefer-bigger-splits/webpack.config.js @@ -11,7 +11,7 @@ const stats = { module.exports = { mode: "production", entry: { - main: "./", + main: "./" }, output: { filename: "default/[name].js" diff --git a/test/statsCases/split-chunks/webpack.config.js b/test/statsCases/split-chunks/webpack.config.js index c8c1b8d13..c1c5fd26d 100644 --- a/test/statsCases/split-chunks/webpack.config.js +++ b/test/statsCases/split-chunks/webpack.config.js @@ -9,7 +9,6 @@ const stats = { modules: false }; module.exports = [ - { name: "default", mode: "production", @@ -100,5 +99,4 @@ module.exports = [ }, stats } - ]; diff --git a/test/statsCases/warnings-uglifyjs/webpack.config.js b/test/statsCases/warnings-uglifyjs/webpack.config.js index 6ca2aca02..2bdb59940 100644 --- a/test/statsCases/warnings-uglifyjs/webpack.config.js +++ b/test/statsCases/warnings-uglifyjs/webpack.config.js @@ -12,7 +12,7 @@ module.exports = { sourceMap: true, uglifyOptions: { compress: { - warnings: true, + warnings: true }, mangle: false, output: { diff --git a/test/watchCases/plugins/automatic-prefetch-plugin/webpack.config.js b/test/watchCases/plugins/automatic-prefetch-plugin/webpack.config.js index 845a12450..a33728b6c 100644 --- a/test/watchCases/plugins/automatic-prefetch-plugin/webpack.config.js +++ b/test/watchCases/plugins/automatic-prefetch-plugin/webpack.config.js @@ -1,6 +1,4 @@ var webpack = require("../../../../"); module.exports = { - plugins: [ - new webpack.AutomaticPrefetchPlugin() - ] + plugins: [new webpack.AutomaticPrefetchPlugin()] }; diff --git a/test/watchCases/plugins/dll-reference-plugin/webpack.config.js b/test/watchCases/plugins/dll-reference-plugin/webpack.config.js index 76b20113e..14a6d08cc 100644 --- a/test/watchCases/plugins/dll-reference-plugin/webpack.config.js +++ b/test/watchCases/plugins/dll-reference-plugin/webpack.config.js @@ -10,7 +10,7 @@ module.exports = { buildMeta: { exportsType: "namespace", providedExports: ["default"] - }, + } } } }), diff --git a/test/watchCases/plugins/watch-ignore-plugin/webpack.config.js b/test/watchCases/plugins/watch-ignore-plugin/webpack.config.js index 2dfc851bf..a24d87e2f 100644 --- a/test/watchCases/plugins/watch-ignore-plugin/webpack.config.js +++ b/test/watchCases/plugins/watch-ignore-plugin/webpack.config.js @@ -1,7 +1,5 @@ var webpack = require("../../../../"); module.exports = { - plugins: [ - new webpack.WatchIgnorePlugin([/file\.js$/, /foo$/]) - ] + plugins: [new webpack.WatchIgnorePlugin([/file\.js$/, /foo$/])] }; diff --git a/test/watchCases/simple/multi-compiler/webpack.config.js b/test/watchCases/simple/multi-compiler/webpack.config.js index 8e470217e..24bc32aca 100644 --- a/test/watchCases/simple/multi-compiler/webpack.config.js +++ b/test/watchCases/simple/multi-compiler/webpack.config.js @@ -1,13 +1,16 @@ -module.exports = [{ - name: "changing", - entry: "./index.js", - output: { - filename: "./bundle.js" +module.exports = [ + { + name: "changing", + entry: "./index.js", + output: { + filename: "./bundle.js" + } + }, + { + name: "static", + entry: "./static-file.js", + output: { + filename: "./static.js" + } } -}, { - name: "static", - entry: "./static-file.js", - output: { - filename: "./static.js" - } -}]; +]; From f32bd41c52b00f6251deda00afa6853324f74ada Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sun, 25 Feb 2018 02:15:37 +0100 Subject: [PATCH 010/162] fix linting --- lib/Chunk.js | 2 +- lib/HotModuleReplacement.runtime.js | 6 +++--- lib/Module.js | 2 +- lib/MultiCompiler.js | 4 ++-- lib/Parser.js | 4 +++- lib/Stats.js | 2 +- lib/node/NodeMainTemplate.runtime.js | 6 +++--- lib/node/NodeMainTemplateAsync.runtime.js | 6 +++--- lib/optimize/AggressiveSplittingPlugin.js | 2 +- lib/optimize/SplitChunksPlugin.js | 2 +- lib/web/JsonpMainTemplate.runtime.js | 6 +++--- lib/webworker/WebWorkerMainTemplate.runtime.js | 8 ++++---- test/BenchmarkTestCases.benchmark.js | 6 +++--- test/ConfigTestCases.test.js | 2 +- test/HotModuleReplacementPlugin.test.js | 4 ++-- test/Parser.unittest.js | 4 +++- test/WatchDetection.test.js | 8 ++++---- test/WatchTestCases.test.js | 2 +- 18 files changed, 40 insertions(+), 36 deletions(-) diff --git a/lib/Chunk.js b/lib/Chunk.js index 529bc0471..296f09b9c 100644 --- a/lib/Chunk.js +++ b/lib/Chunk.js @@ -162,8 +162,8 @@ class Chunk { if (this._modules.size < otherChunk._modules.size) return 1; const a = this._modules[Symbol.iterator](); const b = otherChunk._modules[Symbol.iterator](); + // eslint-disable-next-line while (true) { - // eslint-disable-line const aItem = a.next(); const bItem = b.next(); if (aItem.done) return 0; diff --git a/lib/HotModuleReplacement.runtime.js b/lib/HotModuleReplacement.runtime.js index 176f84d07..24e49d1d9 100644 --- a/lib/HotModuleReplacement.runtime.js +++ b/lib/HotModuleReplacement.runtime.js @@ -12,8 +12,8 @@ module.exports = function() { var hotCurrentParents = []; // eslint-disable-line no-unused-vars var hotCurrentParentsTemp = []; // eslint-disable-line no-unused-vars + // eslint-disable-next-line no-unused-vars function hotCreateRequire(moduleId) { - // eslint-disable-line no-unused-vars var me = installedModules[moduleId]; if (!me) return $require$; var fn = function(request) { @@ -80,8 +80,8 @@ module.exports = function() { return fn; } + // eslint-disable-next-line no-unused-vars function hotCreateModule(moduleId) { - // eslint-disable-line no-unused-vars var hot = { // private stuff _acceptedDependencies: {}, @@ -206,8 +206,8 @@ module.exports = function() { }); } + // eslint-disable-next-line no-unused-vars function hotAddUpdateChunk(chunkId, moreModules) { - // eslint-disable-line no-unused-vars if (!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId]) return; hotRequestedFilesMap[chunkId] = false; diff --git a/lib/Module.js b/lib/Module.js index afd38e5b1..73c6c30f4 100644 --- a/lib/Module.js +++ b/lib/Module.js @@ -163,8 +163,8 @@ class Module extends DependenciesBlock { otherModule._chunks.sortWith(sortByDebugId); const a = this._chunks[Symbol.iterator](); const b = otherModule._chunks[Symbol.iterator](); + // eslint-disable-next-line no-constant-condition while (true) { - // eslint-disable-line const aItem = a.next(); const bItem = b.next(); if (aItem.done) return true; diff --git a/lib/MultiCompiler.js b/lib/MultiCompiler.js index 1efdc6d85..31a504dbb 100644 --- a/lib/MultiCompiler.js +++ b/lib/MultiCompiler.js @@ -34,8 +34,8 @@ module.exports = class MultiCompiler extends Tapable { for (const compiler of this.compilers) { let compilerDone = false; const compilerIndex = index++; + // eslint-disable-next-line no-loop-func compiler.hooks.done.tap("MultiCompiler", stats => { - // eslint-disable-line no-loop-func if (!compilerDone) { compilerDone = true; doneCompilers++; @@ -45,8 +45,8 @@ module.exports = class MultiCompiler extends Tapable { this.hooks.done.call(new MultiStats(compilerStats)); } }); + // eslint-disable-next-line no-loop-func compiler.hooks.invalid.tap("MultiCompiler", () => { - // eslint-disable-line no-loop-func if (compilerDone) { compilerDone = false; doneCompilers--; diff --git a/lib/Parser.js b/lib/Parser.js index da8fe4bf8..7ca4d5426 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -2055,7 +2055,9 @@ class Parser extends Tapable { try { ast = acorn.parse(code, parserOptions); threw = false; - } catch (e) {} + } catch (e) { + threw = true; + } } if (threw) { diff --git a/lib/Stats.js b/lib/Stats.js index 4b4ccc3d0..f0d62ea0a 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -97,7 +97,7 @@ class Stats { if (typeof item === "string") { const regExp = new RegExp( `[\\\\/]${item.replace( - /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, + /[-[\]{}()*+?.\\^$|]/g, "\\$&" )}([\\\\/]|$|!|\\?)` ); // eslint-disable-line no-useless-escape diff --git a/lib/node/NodeMainTemplate.runtime.js b/lib/node/NodeMainTemplate.runtime.js index b8ab8c4c7..d34388bf7 100644 --- a/lib/node/NodeMainTemplate.runtime.js +++ b/lib/node/NodeMainTemplate.runtime.js @@ -4,14 +4,14 @@ */ /*global installedChunks $hotChunkFilename$ hotAddUpdateChunk $hotMainFilename$ */ module.exports = function() { + // eslint-disable-next-line no-unused-vars function hotDownloadUpdateChunk(chunkId) { - // eslint-disable-line no-unused-vars var chunk = require("./" + $hotChunkFilename$); hotAddUpdateChunk(chunk.id, chunk.modules); } + // eslint-disable-next-line no-unused-vars function hotDownloadManifest() { - // eslint-disable-line no-unused-vars try { var update = require("./" + $hotMainFilename$); } catch (e) { @@ -20,8 +20,8 @@ module.exports = function() { return Promise.resolve(update); } + //eslint-disable-next-line no-unused-vars function hotDisposeChunk(chunkId) { - //eslint-disable-line no-unused-vars delete installedChunks[chunkId]; } }; diff --git a/lib/node/NodeMainTemplateAsync.runtime.js b/lib/node/NodeMainTemplateAsync.runtime.js index 2103e0c57..fb722501c 100644 --- a/lib/node/NodeMainTemplateAsync.runtime.js +++ b/lib/node/NodeMainTemplateAsync.runtime.js @@ -4,8 +4,8 @@ */ /*global installedChunks $hotChunkFilename$ $require$ hotAddUpdateChunk $hotMainFilename$ */ module.exports = function() { + // eslint-disable-next-line no-unused-vars function hotDownloadUpdateChunk(chunkId) { - // eslint-disable-line no-unused-vars var filename = require("path").join(__dirname, $hotChunkFilename$); require("fs").readFile(filename, "utf-8", function(err, content) { if (err) { @@ -21,8 +21,8 @@ module.exports = function() { }); } + // eslint-disable-next-line no-unused-vars function hotDownloadManifest() { - // eslint-disable-line no-unused-vars var filename = require("path").join(__dirname, $hotMainFilename$); return new Promise(function(resolve, reject) { require("fs").readFile(filename, "utf-8", function(err, content) { @@ -37,8 +37,8 @@ module.exports = function() { }); } + //eslint-disable-next-line no-unused-vars function hotDisposeChunk(chunkId) { - //eslint-disable-line no-unused-vars delete installedChunks[chunkId]; } }; diff --git a/lib/optimize/AggressiveSplittingPlugin.js b/lib/optimize/AggressiveSplittingPlugin.js index 2c5b6b63d..d7ad68be0 100644 --- a/lib/optimize/AggressiveSplittingPlugin.js +++ b/lib/optimize/AggressiveSplittingPlugin.js @@ -158,8 +158,8 @@ class AggressiveSplittingPlugin { modulesB.sort(); const aI = modulesA[Symbol.iterator](); const bI = modulesB[Symbol.iterator](); + // eslint-disable-next-line no-constant-condition while (true) { - // eslint-disable-line const aItem = aI.next(); const bItem = bI.next(); if (aItem.done) return 0; diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index fb8dc116c..4a4c599a9 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -66,8 +66,8 @@ const compareEntries = (a, b) => { modulesB.sort(); const aI = modulesA[Symbol.iterator](); const bI = modulesB[Symbol.iterator](); + // eslint-disable-next-line no-constant-condition while (true) { - // eslint-disable-line const aItem = aI.next(); const bItem = bI.next(); if (aItem.done) return 0; diff --git a/lib/web/JsonpMainTemplate.runtime.js b/lib/web/JsonpMainTemplate.runtime.js index a4e32efe4..359cfeadf 100644 --- a/lib/web/JsonpMainTemplate.runtime.js +++ b/lib/web/JsonpMainTemplate.runtime.js @@ -4,14 +4,14 @@ */ /*globals hotAddUpdateChunk parentHotUpdateCallback document XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ $crossOriginLoading$ */ module.exports = function() { + // eslint-disable-next-line no-unused-vars function webpackHotUpdateCallback(chunkId, moreModules) { - // eslint-disable-line no-unused-vars hotAddUpdateChunk(chunkId, moreModules); if (parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); } //$semicolon + // eslint-disable-next-line no-unused-vars function hotDownloadUpdateChunk(chunkId) { - // eslint-disable-line no-unused-vars var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.charset = "utf-8"; @@ -20,8 +20,8 @@ module.exports = function() { head.appendChild(script); } + // eslint-disable-next-line no-unused-vars function hotDownloadManifest(requestTimeout) { - // eslint-disable-line no-unused-vars requestTimeout = requestTimeout || 10000; return new Promise(function(resolve, reject) { if (typeof XMLHttpRequest === "undefined") diff --git a/lib/webworker/WebWorkerMainTemplate.runtime.js b/lib/webworker/WebWorkerMainTemplate.runtime.js index 405f2d9cb..9eab2f1bc 100644 --- a/lib/webworker/WebWorkerMainTemplate.runtime.js +++ b/lib/webworker/WebWorkerMainTemplate.runtime.js @@ -4,19 +4,19 @@ */ /*globals installedChunks hotAddUpdateChunk parentHotUpdateCallback importScripts XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ */ module.exports = function() { + // eslint-disable-next-line no-unused-vars function webpackHotUpdateCallback(chunkId, moreModules) { - // eslint-disable-line no-unused-vars hotAddUpdateChunk(chunkId, moreModules); if (parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); } //$semicolon + // eslint-disable-next-line no-unused-vars function hotDownloadUpdateChunk(chunkId) { - // eslint-disable-line no-unused-vars importScripts($require$.p + $hotChunkFilename$); } + // eslint-disable-next-line no-unused-vars function hotDownloadManifest(requestTimeout) { - // eslint-disable-line no-unused-vars requestTimeout = requestTimeout || 10000; return new Promise(function(resolve, reject) { if (typeof XMLHttpRequest === "undefined") @@ -57,8 +57,8 @@ module.exports = function() { }); } + //eslint-disable-next-line no-unused-vars function hotDisposeChunk(chunkId) { - //eslint-disable-line no-unused-vars delete installedChunks[chunkId]; } }; diff --git a/test/BenchmarkTestCases.benchmark.js b/test/BenchmarkTestCases.benchmark.js index da2833143..031d333a8 100644 --- a/test/BenchmarkTestCases.benchmark.js +++ b/test/BenchmarkTestCases.benchmark.js @@ -22,10 +22,10 @@ describe("BenchmarkTestCases", function() { try { fs.mkdirSync(path.join(__dirname, "js")); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty try { fs.mkdirSync(baselinesPath); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty before(function(done) { this.timeout(270000); @@ -43,7 +43,7 @@ describe("BenchmarkTestCases", function() { } else { try { fs.mkdirSync(baselinePath); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty const gitIndex = path.resolve(rootPath, ".git/index"); const index = fs.readFileSync(gitIndex); git(rootPath).raw( diff --git a/test/ConfigTestCases.test.js b/test/ConfigTestCases.test.js index 8677f8fb9..3622b5749 100644 --- a/test/ConfigTestCases.test.js +++ b/test/ConfigTestCases.test.js @@ -87,7 +87,7 @@ describe("ConfigTestCases", () => { testConfig, require(path.join(testDirectory, "test.config.js")) ); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty this.timeout(testConfig.timeout); diff --git a/test/HotModuleReplacementPlugin.test.js b/test/HotModuleReplacementPlugin.test.js index 519e10a15..e56529d10 100644 --- a/test/HotModuleReplacementPlugin.test.js +++ b/test/HotModuleReplacementPlugin.test.js @@ -23,10 +23,10 @@ describe("HotModuleReplacementPlugin", function() { const recordsFile = path.join(__dirname, "js", "records.json"); try { fs.mkdirSync(path.join(__dirname, "js")); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty try { fs.unlinkSync(recordsFile); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty const compiler = webpack({ cache: false, entry: entryFile, diff --git a/test/Parser.unittest.js b/test/Parser.unittest.js index 54308af2e..da31c04da 100644 --- a/test/Parser.unittest.js +++ b/test/Parser.unittest.js @@ -475,8 +475,10 @@ describe("Parser", () => { "wrapped=['str' string=str]+['four' string=four]", "'str'.concat(obj, 'one', 'two').concat('three', obj, 'four', 'five')": "wrapped=['str' string=str]+['four', 'five' string=fourfive]", + // eslint-disable-next-line no-template-curly-in-string "`start${obj}mid${obj2}end`": - "template=[start string=start],[mid string=mid],[end string=end]", // eslint-disable-line no-template-curly-in-string + "template=[start string=start],[mid string=mid],[end string=end]", + // eslint-disable-next-line no-template-curly-in-string "`start${'str'}mid${obj2}end`": "template=[start${'str'}mid string=startstrmid],[end string=end]", // eslint-disable-line no-template-curly-in-string "'abc'.substr(1)": "string=bc", diff --git a/test/WatchDetection.test.js b/test/WatchDetection.test.js index fcdd6601d..f801a4d7c 100644 --- a/test/WatchDetection.test.js +++ b/test/WatchDetection.test.js @@ -35,7 +35,7 @@ describe("WatchDetection", () => { before(() => { try { fs.mkdirSync(fixturePath); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty fs.writeFileSync(filePath, "require('./file2')", "utf-8"); fs.writeFileSync(file2Path, "original", "utf-8"); }); @@ -43,13 +43,13 @@ describe("WatchDetection", () => { setTimeout(() => { try { fs.unlinkSync(filePath); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty try { fs.unlinkSync(file2Path); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty try { fs.rmdirSync(fixturePath); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty done(); }, 100); // cool down a bit }); diff --git a/test/WatchTestCases.test.js b/test/WatchTestCases.test.js index 82e3bf8a7..ea4a3c6f5 100644 --- a/test/WatchTestCases.test.js +++ b/test/WatchTestCases.test.js @@ -285,7 +285,7 @@ describe("WatchTestCases", () => { testDirectory, "test.config.js" )); - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty if (testConfig.noTests) return process.nextTick(done); _require( From b6396e77c6a1ab034c9efb6e929e7f8e88efdd5e Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sun, 25 Feb 2018 02:21:21 +0100 Subject: [PATCH 011/162] update stats --- test/statsCases/filter-warnings/expected.txt | 28 +++++++++---------- .../statsCases/warnings-uglifyjs/expected.txt | 4 +-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/statsCases/filter-warnings/expected.txt b/test/statsCases/filter-warnings/expected.txt index 21f3dca25..9e37978c9 100644 --- a/test/statsCases/filter-warnings/expected.txt +++ b/test/statsCases/filter-warnings/expected.txt @@ -1,6 +1,6 @@ -Hash: 544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33544a1b5857637a949b33 +Hash: abbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318adabbea59d067e262318ad Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -20,49 +20,49 @@ Child Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0] Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -82,7 +82,7 @@ Child Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0] Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -102,7 +102,7 @@ Child Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0] Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -122,7 +122,7 @@ Child Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0] Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -142,7 +142,7 @@ Child Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0] Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -162,7 +162,7 @@ Child Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0] Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0] Child - Hash: 544a1b5857637a949b33 + Hash: abbea59d067e262318ad Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names diff --git a/test/statsCases/warnings-uglifyjs/expected.txt b/test/statsCases/warnings-uglifyjs/expected.txt index 044ffe43c..f10b033cd 100644 --- a/test/statsCases/warnings-uglifyjs/expected.txt +++ b/test/statsCases/warnings-uglifyjs/expected.txt @@ -1,4 +1,4 @@ -Hash: 2d94d00e348948925d75 +Hash: 5f08c421d55ae2ad3d0e Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names @@ -6,7 +6,7 @@ bundle.js 2.19 KiB 0 [emitted] main Entrypoint main = bundle.js [0] ./index.js 299 bytes {0} [built] [1] ./a.js 249 bytes {0} [built] - [2] (webpack)/buildin/module.js 495 bytes {0} [built] + [2] (webpack)/buildin/module.js 497 bytes {0} [built] WARNING in bundle.js from UglifyJs Dropping unused function someUnRemoteUsedFunction1 [./a.js:3,0] From 213226ece261a0e89edb9de15fbc6775418f6041 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sun, 25 Feb 2018 03:37:44 +0100 Subject: [PATCH 012/162] 4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09ed831a5..1ea24a43c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "4.0.0-beta.3", + "version": "4.0.0", "author": "Tobias Koppers @sokra", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "license": "MIT", From 20452eb4446be3b5ba00662512c18c20eea48f03 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:23:03 +0000 Subject: [PATCH 013/162] spelling: applies --- test/DependenciesBlockVariable.unittest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/DependenciesBlockVariable.unittest.js b/test/DependenciesBlockVariable.unittest.js index 5e8dcb1c9..f056429f5 100644 --- a/test/DependenciesBlockVariable.unittest.js +++ b/test/DependenciesBlockVariable.unittest.js @@ -59,7 +59,7 @@ describe("DependenciesBlockVariable", () => { before(() => (applyMock = sandbox.spy())); - it("aplies information inside dependency templates", () => { + it("applies information inside dependency templates", () => { dependencyTemplates = { get: function() { return { @@ -75,7 +75,7 @@ describe("DependenciesBlockVariable", () => { should(applyMock.calledOnce).be.true(); }); - it("aplies information inside dependency templates", () => { + it("applies information inside dependency templates", () => { dependencyTemplates = { get: function() { return false; From b39266121a806598a288a72f87c077bd6034947e Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:25:03 +0000 Subject: [PATCH 014/162] spelling: assembly --- examples/wasm-simple/README.md | 2 +- lib/node/ReadFileCompileWasmMainTemplatePlugin.js | 2 +- lib/web/FetchCompileWasmMainTemplatePlugin.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/wasm-simple/README.md b/examples/wasm-simple/README.md index e41692c95..6c9d27ac3 100644 --- a/examples/wasm-simple/README.md +++ b/examples/wasm-simple/README.md @@ -242,7 +242,7 @@ export function fibonacciJavascript(i) { /******/ // on error function for async loading /******/ __webpack_require__.oe = function(err) { console.error(err); throw err; }; /******/ -/******/ // object with all compiled WebAssmbly.Modules +/******/ // object with all compiled WebAssembly.Modules /******/ __webpack_require__.w = {}; /******/ /******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; diff --git a/lib/node/ReadFileCompileWasmMainTemplatePlugin.js b/lib/node/ReadFileCompileWasmMainTemplatePlugin.js index 1e8a8d60b..6a57326a8 100644 --- a/lib/node/ReadFileCompileWasmMainTemplatePlugin.js +++ b/lib/node/ReadFileCompileWasmMainTemplatePlugin.js @@ -97,7 +97,7 @@ class ReadFileCompileWasmMainTemplatePlugin { return Template.asString([ source, "", - "// object with all compiled WebAssmbly.Modules", + "// object with all compiled WebAssembly.Modules", `${mainTemplate.requireFn}.w = {};` ]); } diff --git a/lib/web/FetchCompileWasmMainTemplatePlugin.js b/lib/web/FetchCompileWasmMainTemplatePlugin.js index 447f695db..e0e52c32c 100644 --- a/lib/web/FetchCompileWasmMainTemplatePlugin.js +++ b/lib/web/FetchCompileWasmMainTemplatePlugin.js @@ -104,7 +104,7 @@ class FetchCompileWasmMainTemplatePlugin { return Template.asString([ source, "", - "// object with all compiled WebAssmbly.Modules", + "// object with all compiled WebAssembly.Modules", `${mainTemplate.requireFn}.w = {};` ]); } From 7fcc1d0902a261621bb24f6fbf028fcc03a7f4a0 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:25:27 +0000 Subject: [PATCH 015/162] spelling: brackets --- test/configCases/plugins/define-plugin/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/configCases/plugins/define-plugin/index.js b/test/configCases/plugins/define-plugin/index.js index 1e2051e50..02c3dff70 100644 --- a/test/configCases/plugins/define-plugin/index.js +++ b/test/configCases/plugins/define-plugin/index.js @@ -81,7 +81,7 @@ it("should assign to process.env", function() { process.env.TEST = "test"; process.env.TEST.should.be.eql("test"); }); -it("should not have brakets on start", function() { +it("should not have brackets on start", function() { function f() { throw new Error("should not be called"); } From 676e74660a5fefa1c867aa72ee8543d81e80a6d2 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:26:06 +0000 Subject: [PATCH 016/162] spelling: chosen --- lib/optimize/SplitChunksPlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 4a4c599a9..9cbd34087 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -431,7 +431,7 @@ module.exports = class SplitChunksPlugin { } if (chunkName) { newChunk.chunkReason += ` (name: ${chunkName})`; - // If the choosen name is already an entry point we remove the entry point + // If the chosen name is already an entry point we remove the entry point const entrypoint = compilation.entrypoints.get(chunkName); if (entrypoint) { compilation.entrypoints.delete(chunkName); From 93932e807606cff4fbd0b9f451ba1bb84860e71d Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:26:28 +0000 Subject: [PATCH 017/162] spelling: codecov --- open-bot.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/open-bot.yaml b/open-bot.yaml index 73c8b8b27..a77395834 100644 --- a/open-bot.yaml +++ b/open-bot.yaml @@ -196,7 +196,7 @@ rules: -# Add tests-needed label depending on codedov status +# Add tests-needed label depending on codecov status # comment to point the user writing test cases # comment in case of success - filters: From 885a8df7292cb0ca5f3880465597b045f101902f Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:26:51 +0000 Subject: [PATCH 018/162] spelling: concatenation --- examples/scope-hoisting/README.md | 2 +- examples/scope-hoisting/template.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/scope-hoisting/README.md b/examples/scope-hoisting/README.md index 24cfd34b9..cfa1896e4 100644 --- a/examples/scope-hoisting/README.md +++ b/examples/scope-hoisting/README.md @@ -18,7 +18,7 @@ webpack therefore uses a approach called **"Partial Scope Hoisting"** or "Module ![](graph3.png) -While module concatentation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs. +While module concatenation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs. # example.js diff --git a/examples/scope-hoisting/template.md b/examples/scope-hoisting/template.md index 2aaf5408c..077229d82 100644 --- a/examples/scope-hoisting/template.md +++ b/examples/scope-hoisting/template.md @@ -18,7 +18,7 @@ webpack therefore uses a approach called **"Partial Scope Hoisting"** or "Module ![](graph3.png) -While module concatentation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs. +While module concatenation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs. # example.js From 8728659adae99c6592a8fc1e9155a7e136bfa5d1 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:27:08 +0000 Subject: [PATCH 019/162] spelling: concord --- schemas/WebpackOptions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index f9b8e2933..347319254 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -718,7 +718,7 @@ "type": "boolean" }, "concord": { - "description": "Enable condord resolving extras", + "description": "Enable concord resolving extras", "type": "boolean" }, "unsafeCache": { From 96ebb27964f42632cfdaca0cd7a6fabbfceb5676 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:27:17 +0000 Subject: [PATCH 020/162] spelling: connect --- lib/Compilation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Compilation.js b/lib/Compilation.js index ff7470869..836d71437 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -1338,7 +1338,7 @@ class Compilation extends Tapable { const depChunkGroup = dep.chunkGroup; const depBlock = dep.block; - // 6. Connnect block with chunk + // 6. Connect block with chunk GraphHelpers.connectDependenciesBlockAndChunkGroup( depBlock, depChunkGroup From 5e49e8c7be92e411048b7b38eba3682416854134 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:27:30 +0000 Subject: [PATCH 021/162] spelling: dependencies --- test/cases/parsing/extract-amd.nominimize/index.js | 2 +- test/cases/parsing/extract-amd/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cases/parsing/extract-amd.nominimize/index.js b/test/cases/parsing/extract-amd.nominimize/index.js index f125efeed..a29bd7578 100644 --- a/test/cases/parsing/extract-amd.nominimize/index.js +++ b/test/cases/parsing/extract-amd.nominimize/index.js @@ -54,7 +54,7 @@ it("should be able to use require.js-style define with arrow functions", functio }); }); -it("should be able to use require.js-style define, optional dependancies, not exist, with arrow function", function(done) { +it("should be able to use require.js-style define, optional dependencies, not exist, with arrow function", function(done) { define("name", ["./optional"], (optional) => { should(optional.b).not.exist; done(); diff --git a/test/cases/parsing/extract-amd/index.js b/test/cases/parsing/extract-amd/index.js index 5b7738002..4299ede63 100644 --- a/test/cases/parsing/extract-amd/index.js +++ b/test/cases/parsing/extract-amd/index.js @@ -54,7 +54,7 @@ it("should be able to use require.js-style define", function(done) { }); }); -it("should be able to use require.js-style define, optional dependancies, not exist", function(done) { +it("should be able to use require.js-style define, optional dependencies, not exist", function(done) { define("name", ["./optional"], function(optional) { should(optional.b).not.exist; done(); From 9b046aee7340ad8bfbd2947e0a7d5a57c73de40b Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:27:40 +0000 Subject: [PATCH 022/162] spelling: describing --- test/Schemas.lint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Schemas.lint.js b/test/Schemas.lint.js index 13b053488..619c80ece 100644 --- a/test/Schemas.lint.js +++ b/test/Schemas.lint.js @@ -119,7 +119,7 @@ describe("Schemas", () => { }); } if ("properties" in item) { - it("should have additionalProperties set to some value when descriping properties", () => { + it("should have additionalProperties set to some value when describing properties", () => { item.should.be.property("additionalProperties"); }); Object.keys(item.properties).forEach(name => { From 89932f0d715786453bcf0420e1c5bb43bdb0ef74 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:28:07 +0000 Subject: [PATCH 023/162] spelling: equivalent --- examples/harmony-interop/README.md | 4 ++-- examples/harmony-interop/fs.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/harmony-interop/README.md b/examples/harmony-interop/README.md index bb1814910..2f6f20561 100644 --- a/examples/harmony-interop/README.md +++ b/examples/harmony-interop/README.md @@ -29,7 +29,7 @@ exports.readFile = function() {}; // using module.exports would be equivalent, // webpack doesn't care which syntax is used -// AMD modules are also possible and equvivalent to CommonJs modules +// AMD modules are also possible and equivalent to CommonJs modules ``` # reexport-commonjs.js @@ -192,7 +192,7 @@ exports.readFile = function() {}; // using module.exports would be equivalent, // webpack doesn't care which syntax is used -// AMD modules are also possible and equvivalent to CommonJs modules +// AMD modules are also possible and equivalent to CommonJs modules /***/ }), diff --git a/examples/harmony-interop/fs.js b/examples/harmony-interop/fs.js index 3f89f696d..93ac6b60f 100644 --- a/examples/harmony-interop/fs.js +++ b/examples/harmony-interop/fs.js @@ -4,4 +4,4 @@ exports.readFile = function() {}; // using module.exports would be equivalent, // webpack doesn't care which syntax is used -// AMD modules are also possible and equvivalent to CommonJs modules +// AMD modules are also possible and equivalent to CommonJs modules From f07ec56837dbb0ae20133ddccc819614b3f9f91c Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:28:20 +0000 Subject: [PATCH 024/162] spelling: existence --- test/ExternalModule.unittest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ExternalModule.unittest.js b/test/ExternalModule.unittest.js index abafa5ed6..9abd104e5 100644 --- a/test/ExternalModule.unittest.js +++ b/test/ExternalModule.unittest.js @@ -204,7 +204,7 @@ describe("ExternalModule", function() { result.should.eql(expected); }); describe("given an optinal check is set", function() { - it("ads a check for the existance of the variable before looking it up", function() { + it("ads a check for the existence of the variable before looking it up", function() { // set up const id = "someId"; const optional = true; @@ -237,7 +237,7 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_someId__;`; result.should.eql(expected); }); describe("given an optinal check is requested", function() { - it("checks for the existance of the request setting it", function() { + it("checks for the existence of the request setting it", function() { // set up const optional = true; const expected = `if(typeof some/request === 'undefined') {var e = new Error("Cannot find module \\"some/request\\""); e.code = 'MODULE_NOT_FOUND'; throw e;} From 64fa1d4e767959e64bd318fd969f1a0c2af1f07c Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:28:31 +0000 Subject: [PATCH 025/162] spelling: extensions --- schemas/WebpackOptions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index 347319254..62b8ee077 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -680,7 +680,7 @@ ] }, "moduleExtensions": { - "description": "Extenstions added to the module request when trying to find the module", + "description": "Extensions added to the module request when trying to find the module", "anyOf": [ { "$ref": "#/definitions/common.arrayOfStringValues" From 2b65b377b0b097c4cac9c4db4db58967f8a9fe57 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:28:40 +0000 Subject: [PATCH 026/162] spelling: falsy --- test/RawModule.unittest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/RawModule.unittest.js b/test/RawModule.unittest.js index a9b56ff26..e4e7b8793 100644 --- a/test/RawModule.unittest.js +++ b/test/RawModule.unittest.js @@ -61,7 +61,7 @@ describe("RawModule", () => { it( "returns a new RawSource instance with sourceStr attribute provided " + - "as constructor argument if useSourceMap is falsey", + "as constructor argument if useSourceMap is falsy", () => { const rawSource = new RawSource(myRawModule.sourceStr); myRawModule.useSourceMap = false; From bf7c5af2e962ce66e05171601976e863ea0e5aca Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:30:14 +0000 Subject: [PATCH 027/162] spelling: fullfil --- lib/optimize/EnsureChunkConditionsPlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/optimize/EnsureChunkConditionsPlugin.js b/lib/optimize/EnsureChunkConditionsPlugin.js index 990e712e3..5d05ec834 100644 --- a/lib/optimize/EnsureChunkConditionsPlugin.js +++ b/lib/optimize/EnsureChunkConditionsPlugin.js @@ -38,7 +38,7 @@ class EnsureChunkConditionsPlugin { // We reached the entrypoint: fail if (chunkGroup.isInitial()) { throw new Error( - "Cannot fullfill chunk condition of " + module.identifier() + "Cannot fullfil chunk condition of " + module.identifier() ); } // Try placing in all parents From 7355b914da59307df8ac0dec74f36a5d2b7be66a Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:30:35 +0000 Subject: [PATCH 028/162] spelling: guaranteed --- lib/ChunkGroup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ChunkGroup.js b/lib/ChunkGroup.js index 7f765ade3..6a1002710 100644 --- a/lib/ChunkGroup.js +++ b/lib/ChunkGroup.js @@ -245,7 +245,7 @@ class ChunkGroup { * we need to iterate again over the children * to remove this from the childs parents. * This can not be done in the above loop - * as it is not garuanteed that `this._parents` contains anything. + * as it is not guaranteed that `this._parents` contains anything. */ for (const chunkGroup of this._children) { // remove this as parent of every "sub chunk" From f3c2de9fcf3b66e8f822898581cea5f754b857ea Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:31:00 +0000 Subject: [PATCH 029/162] spelling: harmony --- .../HarmonyExportImportedSpecifierDependency.js | 8 ++++---- test/configCases/library/1-use-library/index.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js index b0eefc1fd..6e9cc6840 100644 --- a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +++ b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js @@ -450,7 +450,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS case "reexport-non-harmony-default": return ( - "/* harmony reexport (default from non-hamory) */ " + + "/* harmony reexport (default from non-harmony) */ " + this.getReexportStatement( module, module.isUsed(mode.name), @@ -461,7 +461,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS case "reexport-fake-namespace-object": return ( - "/* harmony reexport (fake namespace object from non-hamory) */ " + + "/* harmony reexport (fake namespace object from non-harmony) */ " + this.getReexportFakeNamespaceObjectStatement( module, module.isUsed(mode.name), @@ -471,7 +471,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS case "rexport-non-harmony-undefined": return ( - "/* harmony reexport (non default export from non-hamory) */ " + + "/* harmony reexport (non default export from non-harmony) */ " + this.getReexportStatement( module, module.isUsed(mode.name), @@ -482,7 +482,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS case "reexport-non-harmony-default-strict": return ( - "/* harmony reexport (default from non-hamory) */ " + + "/* harmony reexport (default from non-harmony) */ " + this.getReexportStatement( module, module.isUsed(mode.name), diff --git a/test/configCases/library/1-use-library/index.js b/test/configCases/library/1-use-library/index.js index 6aa92b911..c8b879c52 100644 --- a/test/configCases/library/1-use-library/index.js +++ b/test/configCases/library/1-use-library/index.js @@ -1,7 +1,7 @@ import d from "library"; import { a, b, external } from "library"; -it("should be able to import hamorny exports from library (" + NAME + ")", function() { +it("should be able to import harmony exports from library (" + NAME + ")", function() { d.should.be.eql("default-value"); a.should.be.eql("a"); b.should.be.eql("b"); From 82c3c289992dc039572f86f3c5d78e9017934a00 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:31:47 +0000 Subject: [PATCH 030/162] spelling: height --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dd6f7baa3..b3b807d81 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
- +

From 42c0c3369ff690cc6f342ecb152096729326a0ae Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:32:23 +0000 Subject: [PATCH 031/162] spelling: information --- test/LocalModulesHelpers.unittest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/LocalModulesHelpers.unittest.js b/test/LocalModulesHelpers.unittest.js index b1cd88f96..8f0fd513a 100644 --- a/test/LocalModulesHelpers.unittest.js +++ b/test/LocalModulesHelpers.unittest.js @@ -41,7 +41,7 @@ describe("LocalModulesHelpers", () => { ).be.eql(null); }); - it("returns local module informtion", () => { + it("returns local module information", () => { const state = { module: "module_sample", localModules: [ From 9856ac6f5f7bf4170a28be9aad09774ad2df1f09 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:32:34 +0000 Subject: [PATCH 032/162] spelling: inlined --- test/cases/parsing/issue-387/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cases/parsing/issue-387/index.js b/test/cases/parsing/issue-387/index.js index 60b2a8c50..535bbcee4 100644 --- a/test/cases/parsing/issue-387/index.js +++ b/test/cases/parsing/issue-387/index.js @@ -33,7 +33,7 @@ it("should parse cujojs UMD modules with deps", function() { module.exports.should.be.eql(1234); }); -it("should parse cujojs UMD modules with inlinded deps", function() { +it("should parse cujojs UMD modules with inlined deps", function() { (function (define) { // using the define signature that triggers AMD-wrapped CommonJS From 6e66634c8526d43cec35417e12f082d97743f3f6 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:33:58 +0000 Subject: [PATCH 033/162] spelling: module --- test/cases/parsing/harmony-commonjs/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cases/parsing/harmony-commonjs/index.js b/test/cases/parsing/harmony-commonjs/index.js index ba4245f15..187eefc12 100644 --- a/test/cases/parsing/harmony-commonjs/index.js +++ b/test/cases/parsing/harmony-commonjs/index.js @@ -8,7 +8,7 @@ it("should pass when required by CommonJS module", function () { it("should pass when use babeljs transpiler", function() { //the following are generated code by use babeljs. // use it this way will save trouble to setup babel-loader - // the babeljs transpiled code depends on the __esMoudule to be set + // the babeljs transpiled code depends on the __esModule to be set var _test = require('./a'); var _test2 = _interopRequireDefault(_test); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } From 4ecd495a5bb573ff008d474ab02df191b56365d1 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:35:18 +0000 Subject: [PATCH 034/162] spelling: number --- test/browsertest/mocha.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/browsertest/mocha.js b/test/browsertest/mocha.js index 9088e2ac1..568e02fcb 100644 --- a/test/browsertest/mocha.js +++ b/test/browsertest/mocha.js @@ -2777,7 +2777,7 @@ function NyanCat(runner) { , width = Base.window.width * .75 | 0 , rainbowColors = this.rainbowColors = self.generateColors() , colorIndex = this.colorIndex = 0 - , numerOfLines = this.numberOfLines = 4 + , numberOfLines = this.numberOfLines = 4 , trajectories = this.trajectories = [[], [], [], []] , nyanCatWidth = this.nyanCatWidth = 11 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) From e2db8f74a4ccef9a9447e9ad5724f97bb6251d41 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:35:40 +0000 Subject: [PATCH 035/162] spelling: object --- test/RuleSet.unittest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/RuleSet.unittest.js b/test/RuleSet.unittest.js index db49675a1..69b6a444d 100644 --- a/test/RuleSet.unittest.js +++ b/test/RuleSet.unittest.js @@ -388,7 +388,7 @@ describe("RuleSet", () => { match(loader, "style.css").should.eql(["style-loader", "css-loader"]); }); - it("should work when using an array of functions returning either a loader obejct or loader name string", () => { + it("should work when using an array of functions returning either a loader object or loader name string", () => { const loader = new RuleSet([ { test: /\.css$/, From 805f4b097addce5980408e18d52039f7f84abcdb Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:36:27 +0000 Subject: [PATCH 036/162] spelling: optional --- test/ExternalModule.unittest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ExternalModule.unittest.js b/test/ExternalModule.unittest.js index 9abd104e5..083eee724 100644 --- a/test/ExternalModule.unittest.js +++ b/test/ExternalModule.unittest.js @@ -203,7 +203,7 @@ describe("ExternalModule", function() { // check result.should.eql(expected); }); - describe("given an optinal check is set", function() { + describe("given an optional check is set", function() { it("ads a check for the existence of the variable before looking it up", function() { // set up const id = "someId"; @@ -236,7 +236,7 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_someId__;`; // check result.should.eql(expected); }); - describe("given an optinal check is requested", function() { + describe("given an optional check is requested", function() { it("checks for the existence of the request setting it", function() { // set up const optional = true; From 0a68e29ea4e65ad076c1725d86f5dd0746858da1 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:36:44 +0000 Subject: [PATCH 037/162] spelling: options --- lib/ErrorHelpers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ErrorHelpers.js b/lib/ErrorHelpers.js index 0c5029a8f..51d8017f3 100644 --- a/lib/ErrorHelpers.js +++ b/lib/ErrorHelpers.js @@ -18,7 +18,7 @@ exports.cutOffByFlag = (stack, flag) => { exports.cutOffLoaderExecution = stack => exports.cutOffByFlag(stack, loaderFlag); -exports.cutOffWebpackOptinos = stack => +exports.cutOffWebpackOptions = stack => exports.cutOffByFlag(stack, webpackOptionsFlag); exports.cutOffMultilineMessage = (stack, message) => { @@ -51,7 +51,7 @@ exports.cleanUp = (stack, message) => { }; exports.cleanUpWebpackOptions = (stack, message) => { - stack = exports.cutOffWebpackOptinos(stack); + stack = exports.cutOffWebpackOptions(stack); stack = exports.cutOffMultilineMessage(stack, message); return stack; }; From 51e149f91c7471a45f792c7abd77bf0ed2fddbf0 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:37:18 +0000 Subject: [PATCH 038/162] spelling: original --- open-bot.yaml | 2 +- test/browsertest/lib/index.web.js | 2 +- test/browsertest/node_modules/subcontent2/file.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/open-bot.yaml b/open-bot.yaml index a77395834..8b50d3e50 100644 --- a/open-bot.yaml +++ b/open-bot.yaml @@ -446,7 +446,7 @@ rules: --- - This issue was moved from {{owner}}/{{repo}}#{{issue.number}} by @{{comment.actor.login}}. Orginal issue was by @{{issue.user.login}}. + This issue was moved from {{owner}}/{{repo}}#{{issue.number}} by @{{comment.actor.login}}. Original issue was by @{{issue.user.login}}. {{{comment_match.[2]}}} comment: diff --git a/test/browsertest/lib/index.web.js b/test/browsertest/lib/index.web.js index 03d13e86e..fe9a593ac 100644 --- a/test/browsertest/lib/index.web.js +++ b/test/browsertest/lib/index.web.js @@ -37,7 +37,7 @@ describe("main", function() { // Comments work! exports.ok = true; test(require("subcontent") === "replaced", "node_modules should be replaced with web_modules"); - test(require("subcontent2/file.js") === "orginal", "node_modules should still work when web_modules exists"); + test(require("subcontent2/file.js") === "original", "node_modules should still work when web_modules exists"); done(); }); }); diff --git a/test/browsertest/node_modules/subcontent2/file.js b/test/browsertest/node_modules/subcontent2/file.js index 6c4acf8b4..249c1aed4 100644 --- a/test/browsertest/node_modules/subcontent2/file.js +++ b/test/browsertest/node_modules/subcontent2/file.js @@ -1 +1 @@ -module.exports = "orginal"; \ No newline at end of file +module.exports = "original"; \ No newline at end of file From 0a4308f1dacb888a61f45ed6a3a55d4cc9639731 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:38:03 +0000 Subject: [PATCH 039/162] spelling: ourself --- lib/debug/ProfilingPlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/debug/ProfilingPlugin.js b/lib/debug/ProfilingPlugin.js index ea63513eb..76fb36f95 100644 --- a/lib/debug/ProfilingPlugin.js +++ b/lib/debug/ProfilingPlugin.js @@ -367,7 +367,7 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => { return (...args) => { // eslint-disable-line const id = ++tracer.counter; - // Do not instrument outself due to the CPU + // Do not instrument ourself due to the CPU // profile needing to be the last event in the trace. if (name === pluginName) { return fn(...args); From c1ccdbe309a38a9ae49c9455daacf7f991125f3a Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:38:10 +0000 Subject: [PATCH 040/162] spelling: output --- test/browsertest/mocha.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/browsertest/mocha.js b/test/browsertest/mocha.js index 568e02fcb..a0d14d349 100644 --- a/test/browsertest/mocha.js +++ b/test/browsertest/mocha.js @@ -1441,7 +1441,7 @@ exports.cursor = { }; /** - * Outut the given `failures` as a list. + * Output the given `failures` as a list. * * @param {Array} failures * @api public From 159299caa03ff5d117cf86adb8a278d607ad52df Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:38:19 +0000 Subject: [PATCH 041/162] spelling: overrides --- test/MultiStats.unittest.js | 6 +++--- test/compareLocations.unittest.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/MultiStats.unittest.js b/test/MultiStats.unittest.js index ccfdb157c..6d096bbb0 100644 --- a/test/MultiStats.unittest.js +++ b/test/MultiStats.unittest.js @@ -4,7 +4,7 @@ require("should"); const packageJSON = require("../package.json"); const MultiStats = require("../lib/MultiStats"); -const createStat = overides => { +const createStat = overrides => { return Object.assign( { hash: "foo", @@ -21,10 +21,10 @@ const createStat = overides => { warnings: [], errors: [] }, - overides + overrides ) }, - overides + overrides ); }; diff --git a/test/compareLocations.unittest.js b/test/compareLocations.unittest.js index 5efc5d3de..4572fd5cf 100644 --- a/test/compareLocations.unittest.js +++ b/test/compareLocations.unittest.js @@ -2,13 +2,13 @@ const should = require("should"); const compareLocations = require("../lib/compareLocations"); -const createPosition = function(overides) { +const createPosition = function(overrides) { return Object.assign( { line: 10, column: 5 }, - overides + overrides ); }; From db7450b1c5947adca16bb7676c530dd1afecb1de Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:38:26 +0000 Subject: [PATCH 042/162] spelling: parameter --- lib/JavascriptGenerator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/JavascriptGenerator.js b/lib/JavascriptGenerator.js index cbefeb86b..94315ce93 100644 --- a/lib/JavascriptGenerator.js +++ b/lib/JavascriptGenerator.js @@ -53,7 +53,7 @@ class JavascriptGenerator { /** * Get the variables of all blocks that we need to inject. * These will contain the variable name and its expression. - * The name will be added as a paramter in a IIFE the expression as its value. + * The name will be added as a parameter in a IIFE the expression as its value. */ const vars = block.variables.reduce((result, value) => { const variable = this.sourceVariables( From 2c30ef37f8f19dfd4250e0af38ecacf1f68bef5d Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:39:15 +0000 Subject: [PATCH 043/162] spelling: passer --- test/Validation.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Validation.test.js b/test/Validation.test.js index ebc80462b..1d40796fb 100644 --- a/test/Validation.test.js +++ b/test/Validation.test.js @@ -176,7 +176,7 @@ describe("Validation", () => { oneOf: [ { test: "/a", - paser: { + passer: { amd: false } } @@ -186,7 +186,7 @@ describe("Validation", () => { } }, message: [ - " - configuration.module.rules[0].oneOf[0] has an unknown property 'paser'. These properties are valid:", + " - configuration.module.rules[0].oneOf[0] has an unknown property 'passer'. These properties are valid:", " object { enforce?, exclude?, include?, issuer?, loader?, loaders?, oneOf?, options?, parser?, resolve?, sideEffects?, query?, type?, resource?, resourceQuery?, compiler?, rules?, test?, use? }", " -> A rule" ] From 82b81eb1dc5155a1f5c089659aaf049d5a2fa9f3 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:39:48 +0000 Subject: [PATCH 044/162] spelling: practice --- examples/common-chunk-grandchildren/README.md | 2 +- examples/common-chunk-grandchildren/webpack.config.js | 2 +- examples/extra-async-chunk/README.md | 2 +- examples/extra-async-chunk/template.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/common-chunk-grandchildren/README.md b/examples/common-chunk-grandchildren/README.md index 2477bfe19..02dc86541 100644 --- a/examples/common-chunk-grandchildren/README.md +++ b/examples/common-chunk-grandchildren/README.md @@ -93,7 +93,7 @@ module.exports = { }, optimization: { splitChunks: { - minSize: 0 // This example is too small, in pratice you can use the defaults + minSize: 0 // This example is too small, in practice you can use the defaults }, occurrenceOrder: true // To keep filename consistent between different modes (for example building only) }, diff --git a/examples/common-chunk-grandchildren/webpack.config.js b/examples/common-chunk-grandchildren/webpack.config.js index 5b5da3e50..189b94895 100644 --- a/examples/common-chunk-grandchildren/webpack.config.js +++ b/examples/common-chunk-grandchildren/webpack.config.js @@ -8,7 +8,7 @@ module.exports = { }, optimization: { splitChunks: { - minSize: 0 // This example is too small, in pratice you can use the defaults + minSize: 0 // This example is too small, in practice you can use the defaults }, occurrenceOrder: true // To keep filename consistent between different modes (for example building only) }, diff --git a/examples/extra-async-chunk/README.md b/examples/extra-async-chunk/README.md index db22c4dce..63e1c69c0 100644 --- a/examples/extra-async-chunk/README.md +++ b/examples/extra-async-chunk/README.md @@ -16,7 +16,7 @@ The example entry references two chunks: These chunks share modules `a` and `b`. The optimization extract these into chunk Z: -Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In pratice there is no configuration needed for this. +Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In practice there is no configuration needed for this. * entry chunk * async require -> chunk X & Z diff --git a/examples/extra-async-chunk/template.md b/examples/extra-async-chunk/template.md index afe51efe8..3e60643c0 100644 --- a/examples/extra-async-chunk/template.md +++ b/examples/extra-async-chunk/template.md @@ -16,7 +16,7 @@ The example entry references two chunks: These chunks share modules `a` and `b`. The optimization extract these into chunk Z: -Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In pratice there is no configuration needed for this. +Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In practice there is no configuration needed for this. * entry chunk * async require -> chunk X & Z From 6b7f27df7229ffb1174dc57b23e189b0fa920af8 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:40:03 +0000 Subject: [PATCH 045/162] spelling: progress --- test/configCases/plugins/progress-plugin/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/configCases/plugins/progress-plugin/index.js b/test/configCases/plugins/progress-plugin/index.js index c17d0bdd1..cf1134394 100644 --- a/test/configCases/plugins/progress-plugin/index.js +++ b/test/configCases/plugins/progress-plugin/index.js @@ -1,4 +1,4 @@ -it("should contain the custom progres messages", function() { +it("should contain the custom progress messages", function() { var data = require(__dirname + "/data"); data.should.containEql("optimizing"); data.should.containEql("optimizing|CustomPlugin"); From 54d55ff9d632db1685ff4c1bde3ba733a7d9eac6 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:40:14 +0000 Subject: [PATCH 046/162] spelling: property --- lib/MainTemplate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MainTemplate.js b/lib/MainTemplate.js index 1fdbf8714..bbb5e50a9 100644 --- a/lib/MainTemplate.js +++ b/lib/MainTemplate.js @@ -21,7 +21,7 @@ const SyncBailHook = require("tapable").SyncBailHook; // __webpack_require__.p = the bundle public path // __webpack_require__.i = the identity function used for harmony imports // __webpack_require__.e = the chunk ensure function -// __webpack_require__.d = the exported propery define getter function +// __webpack_require__.d = the exported property define getter function // __webpack_require__.o = Object.prototype.hasOwnProperty.call // __webpack_require__.r = define compatibility on export // __webpack_require__.n = compatibility get default export From 632bd3d3ad5703cbe0ce09a407a8dca07fc5b3e0 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:41:26 +0000 Subject: [PATCH 047/162] spelling: recursively --- test/configCases/plugins/define-plugin/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/configCases/plugins/define-plugin/index.js b/test/configCases/plugins/define-plugin/index.js index 02c3dff70..5716a30c3 100644 --- a/test/configCases/plugins/define-plugin/index.js +++ b/test/configCases/plugins/define-plugin/index.js @@ -90,12 +90,12 @@ it("should not have brackets on start", function() { }); it("should not explode on recursive typeof calls", function() { - (typeof wurst).should.eql("undefined"); // <- is recursivly defined in config + (typeof wurst).should.eql("undefined"); // <- is recursively defined in config }); it("should not explode on recursive statements", function() { (function() { - wurst; // <- is recursivly defined in config + wurst; // <- is recursively defined in config }).should.throw("suppe is not defined"); }); From af3431d3993d8d10a1e502072932ca03acbb1882 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:43:37 +0000 Subject: [PATCH 048/162] spelling: segment --- lib/ContextModuleFactory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ContextModuleFactory.js b/lib/ContextModuleFactory.js index e11e2d0b7..8ffad567f 100644 --- a/lib/ContextModuleFactory.js +++ b/lib/ContextModuleFactory.js @@ -174,8 +174,8 @@ module.exports = class ContextModuleFactory extends Tapable { if (!files || files.length === 0) return callback(null, []); asyncLib.map( files.filter(p => p.indexOf(".") !== 0), - (seqment, callback) => { - const subResource = path.join(directory, seqment); + (segment, callback) => { + const subResource = path.join(directory, segment); if (!exclude || !subResource.match(exclude)) { fs.stat(subResource, (err, stat) => { From 2d389c7c896b9f2f5a74d2cb9327dda5985c57b6 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:42:40 +0000 Subject: [PATCH 049/162] spelling: sensitive --- test/cases/errors/{case-sensistive => case-sensitive}/a.js | 0 .../errors/{case-sensistive => case-sensitive}/b/file.js | 0 .../cases/errors/{case-sensistive => case-sensitive}/index.js | 0 .../errors/{case-sensistive => case-sensitive}/test.filter.js | 0 .../errors/{case-sensistive => case-sensitive}/warnings.js | 4 ++-- 5 files changed, 2 insertions(+), 2 deletions(-) rename test/cases/errors/{case-sensistive => case-sensitive}/a.js (100%) rename test/cases/errors/{case-sensistive => case-sensitive}/b/file.js (100%) rename test/cases/errors/{case-sensistive => case-sensitive}/index.js (100%) rename test/cases/errors/{case-sensistive => case-sensitive}/test.filter.js (100%) rename test/cases/errors/{case-sensistive => case-sensitive}/warnings.js (54%) diff --git a/test/cases/errors/case-sensistive/a.js b/test/cases/errors/case-sensitive/a.js similarity index 100% rename from test/cases/errors/case-sensistive/a.js rename to test/cases/errors/case-sensitive/a.js diff --git a/test/cases/errors/case-sensistive/b/file.js b/test/cases/errors/case-sensitive/b/file.js similarity index 100% rename from test/cases/errors/case-sensistive/b/file.js rename to test/cases/errors/case-sensitive/b/file.js diff --git a/test/cases/errors/case-sensistive/index.js b/test/cases/errors/case-sensitive/index.js similarity index 100% rename from test/cases/errors/case-sensistive/index.js rename to test/cases/errors/case-sensitive/index.js diff --git a/test/cases/errors/case-sensistive/test.filter.js b/test/cases/errors/case-sensitive/test.filter.js similarity index 100% rename from test/cases/errors/case-sensistive/test.filter.js rename to test/cases/errors/case-sensitive/test.filter.js diff --git a/test/cases/errors/case-sensistive/warnings.js b/test/cases/errors/case-sensitive/warnings.js similarity index 54% rename from test/cases/errors/case-sensistive/warnings.js rename to test/cases/errors/case-sensitive/warnings.js index 4dbb1fff7..99ac2e5cf 100644 --- a/test/cases/errors/case-sensistive/warnings.js +++ b/test/cases/errors/case-sensitive/warnings.js @@ -1,4 +1,4 @@ module.exports = [ - [/There are multiple modules with names that only differ in casing/, /case-sensistive.A\.js/, /case-sensistive.a\.js/], - [/There are multiple modules with names that only differ in casing/, /case-sensistive.B.file\.js/, /case-sensistive.b.file\.js/] + [/There are multiple modules with names that only differ in casing/, /case-sensitive.A\.js/, /case-sensitive.a\.js/], + [/There are multiple modules with names that only differ in casing/, /case-sensitive.B.file\.js/, /case-sensitive.b.file\.js/] ]; From 2ee033b4bc512d9173616319b48bc884a790ee7e Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:43:19 +0000 Subject: [PATCH 050/162] spelling: separate --- examples/common-chunk-grandchildren/README.md | 2 +- examples/common-chunk-grandchildren/template.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/common-chunk-grandchildren/README.md b/examples/common-chunk-grandchildren/README.md index 02dc86541..d9f08f98c 100644 --- a/examples/common-chunk-grandchildren/README.md +++ b/examples/common-chunk-grandchildren/README.md @@ -1,4 +1,4 @@ -This example illustrates how common modules from deep ancestors of an entry point can be split into a seperate common chunk +This example illustrates how common modules from deep ancestors of an entry point can be split into a separate common chunk * `pageA` and `pageB` are dynamically required * `pageC` and `pageA` both require the `reusableComponent` diff --git a/examples/common-chunk-grandchildren/template.md b/examples/common-chunk-grandchildren/template.md index edf7a4267..aa0aaeae9 100644 --- a/examples/common-chunk-grandchildren/template.md +++ b/examples/common-chunk-grandchildren/template.md @@ -1,4 +1,4 @@ -This example illustrates how common modules from deep ancestors of an entry point can be split into a seperate common chunk +This example illustrates how common modules from deep ancestors of an entry point can be split into a separate common chunk * `pageA` and `pageB` are dynamically required * `pageC` and `pageA` both require the `reusableComponent` From 74b060a08e287a1584bbdf9067df9928783ecd98 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:43:09 +0000 Subject: [PATCH 051/162] spelling: separately --- examples/dll-app-and-vendor/0-vendor/README.md | 2 +- examples/dll-app-and-vendor/0-vendor/template.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dll-app-and-vendor/0-vendor/README.md b/examples/dll-app-and-vendor/0-vendor/README.md index f85646a01..be4fe8eeb 100644 --- a/examples/dll-app-and-vendor/0-vendor/README.md +++ b/examples/dll-app-and-vendor/0-vendor/README.md @@ -1,6 +1,6 @@ This is the vendor build part. -It's built separatly from the app part. The vendors dll is only built when vendors has changed and not while the normal development cycle. +It's built separately from the app part. The vendors dll is only built when vendors has changed and not while the normal development cycle. The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target environment. diff --git a/examples/dll-app-and-vendor/0-vendor/template.md b/examples/dll-app-and-vendor/0-vendor/template.md index 99bf5549d..e66f844f1 100644 --- a/examples/dll-app-and-vendor/0-vendor/template.md +++ b/examples/dll-app-and-vendor/0-vendor/template.md @@ -1,6 +1,6 @@ This is the vendor build part. -It's built separatly from the app part. The vendors dll is only built when vendors has changed and not while the normal development cycle. +It's built separately from the app part. The vendors dll is only built when vendors has changed and not while the normal development cycle. The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target environment. From 126efaf1f682fe15fd798d5078aeee1280d6e2ec Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:43:28 +0000 Subject: [PATCH 052/162] spelling: separator --- lib/RequestShortener.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/RequestShortener.js b/lib/RequestShortener.js index 0e2d3d47d..3648dde96 100644 --- a/lib/RequestShortener.js +++ b/lib/RequestShortener.js @@ -31,8 +31,8 @@ class RequestShortener { } const dirname = path.dirname(directory); - const endsWithSeperator = SEPARATOR_REGEXP.test(dirname); - const parentDirectory = endsWithSeperator + const endsWithSeparator = SEPARATOR_REGEXP.test(dirname); + const parentDirectory = endsWithSeparator ? dirname.substr(0, dirname.length - 1) : dirname; if (parentDirectory && parentDirectory !== directory) { From 27916ac33936775c31451ce09511a0300d7861da Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:43:50 +0000 Subject: [PATCH 053/162] spelling: set --- test/WebEnvironmentPlugin.unittest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WebEnvironmentPlugin.unittest.js b/test/WebEnvironmentPlugin.unittest.js index 146b1f277..ce1d87f4f 100644 --- a/test/WebEnvironmentPlugin.unittest.js +++ b/test/WebEnvironmentPlugin.unittest.js @@ -23,7 +23,7 @@ describe("WebEnvironmentPlugin", () => { WebEnvironmentPluginInstance.apply(compileSpy); }); - it("should set compiler.outputFileSystem information with the same as setted in WebEnvironmentPlugin", () => + it("should set compiler.outputFileSystem information with the same as set in WebEnvironmentPlugin", () => should(compileSpy.outputFileSystem).be.eql( WebEnvironmentPluginInstance.outputFileSystem )); From b06c2f270ce0d862c8ceeb3a7f137c3cb62cfc3c Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:45:26 +0000 Subject: [PATCH 054/162] spelling: singular --- test/cases/runtime/module-caching/index.js | 28 +++++++++---------- .../{singluar.js => singular.js} | 0 .../{singluar2.js => singular2.js} | 0 3 files changed, 14 insertions(+), 14 deletions(-) rename test/cases/runtime/module-caching/{singluar.js => singular.js} (100%) rename test/cases/runtime/module-caching/{singluar2.js => singular2.js} (100%) diff --git a/test/cases/runtime/module-caching/index.js b/test/cases/runtime/module-caching/index.js index 7846b43b5..34e70f3cd 100644 --- a/test/cases/runtime/module-caching/index.js +++ b/test/cases/runtime/module-caching/index.js @@ -1,26 +1,26 @@ var should = require("should"); it("should cache modules correctly", function(done) { - delete require.cache[require.resolve("./singluar.js")]; - require("./singluar.js").value.should.be.eql(1); - (require("./singluar.js")).value.should.be.eql(1); - require("./sing" + "luar.js").value = 2; - require("./singluar.js").value.should.be.eql(2); + delete require.cache[require.resolve("./singular.js")]; + require("./singular.js").value.should.be.eql(1); + (require("./singular.js")).value.should.be.eql(1); + require("./sing" + "ular.js").value = 2; + require("./singular.js").value.should.be.eql(2); require.ensure(["./two.js"], function(require) { - require("./singluar.js").value.should.be.eql(2); + require("./singular.js").value.should.be.eql(2); done(); }); }); it("should be able the remove modules from cache with require.cache and require.resolve", function() { - var singlarObj = require("./singluar2"); - var singlarId = require.resolve("./singluar2"); - var singlarIdInConditional = require.resolve(true ? "./singluar2" : "./singluar"); - if(typeof singlarId !== "number" && typeof singlarId !== "string") + var singularObj = require("./singular2"); + var singularId = require.resolve("./singular2"); + var singularIdInConditional = require.resolve(true ? "./singular2" : "./singular"); + if(typeof singularId !== "number" && typeof singularId !== "string") throw new Error("require.resolve should return a number or string"); - singlarIdInConditional.should.be.eql(singlarId); + singularIdInConditional.should.be.eql(singularId); (require.cache).should.have.type("object"); - (require.cache[singlarId]).should.have.type("object"); - delete require.cache[singlarId]; - require("./singluar2").should.be.not.equal(singlarObj); + (require.cache[singularId]).should.have.type("object"); + delete require.cache[singularId]; + require("./singular2").should.be.not.equal(singularObj); }); diff --git a/test/cases/runtime/module-caching/singluar.js b/test/cases/runtime/module-caching/singular.js similarity index 100% rename from test/cases/runtime/module-caching/singluar.js rename to test/cases/runtime/module-caching/singular.js diff --git a/test/cases/runtime/module-caching/singluar2.js b/test/cases/runtime/module-caching/singular2.js similarity index 100% rename from test/cases/runtime/module-caching/singluar2.js rename to test/cases/runtime/module-caching/singular2.js From 6dd212bd4586186a3992c0165f1c0cfbcd9a32e5 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:46:46 +0000 Subject: [PATCH 055/162] spelling: somewhere --- test/identifier.unittest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/identifier.unittest.js b/test/identifier.unittest.js index 9c2134774..4ef2fc33b 100644 --- a/test/identifier.unittest.js +++ b/test/identifier.unittest.js @@ -11,8 +11,8 @@ describe("util/identifier", () => { let context, pathConstruct, expected; beforeEach(() => { context = "/some/dir/"; - pathConstruct = "/some/dir/to/somwhere|some/other/dir!../more/dir"; - expected = "to/somwhere|some/other/dir!../more/dir"; + pathConstruct = "/some/dir/to/somewhere|some/other/dir!../more/dir"; + expected = "to/somewhere|some/other/dir!../more/dir"; }); it("computes the correct relative results for the path construct", () => { From 04917d739ccb2288b0749b8f16e11b87c57db054 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:48:26 +0000 Subject: [PATCH 056/162] spelling: source --- test/ExternalModule.unittest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ExternalModule.unittest.js b/test/ExternalModule.unittest.js index 083eee724..5d90bfff4 100644 --- a/test/ExternalModule.unittest.js +++ b/test/ExternalModule.unittest.js @@ -45,7 +45,7 @@ describe("ExternalModule", function() { it("calls getSource with the result of getSourceString", function() { // set up const expectedString = "something expected stringy"; - const expectedSource = "something expected sourcy"; + const expectedSource = "something expected source"; externalModule.getSource = sinon.stub().returns(expectedSource); externalModule.getSourceString = sinon.stub().returns(expectedString); From c9bb7b770761890f81664851e0c0fd274c0791a0 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:48:51 +0000 Subject: [PATCH 057/162] spelling: successful --- lib/NormalModule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/NormalModule.js b/lib/NormalModule.js index 849aaabac..600d9d0fb 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -267,7 +267,7 @@ class NormalModule extends Module { } markModuleAsErrored(error) { - // Restore build meta from successfull build to keep importing state + // Restore build meta from successful build to keep importing state this.buildMeta = Object.assign({}, this._lastSuccessfulBuildMeta); this.error = error; From ecc7fd2fe5292e75b4503d9fafb2e981bd71a444 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:49:06 +0000 Subject: [PATCH 058/162] spelling: suppressed --- lib/Stats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Stats.js b/lib/Stats.js index f0d62ea0a..d7a4cb405 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -28,7 +28,7 @@ class Stats { } // create a chain of filters - // if they return "true" a warning should be surpressed + // if they return "true" a warning should be suppressed const normalizedWarningsFilters = [].concat(warningsFilter).map(filter => { if (typeof filter === "string") { return warning => warning.includes(filter); From b923fff8ebbe9e94485a84cbe8a691ac2b12ec52 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:49:41 +0000 Subject: [PATCH 059/162] spelling: typeof --- lib/DefinePlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DefinePlugin.js b/lib/DefinePlugin.js index ac3ffdba3..6114b0518 100644 --- a/lib/DefinePlugin.js +++ b/lib/DefinePlugin.js @@ -122,7 +122,7 @@ class DefinePlugin { * this is needed in case there is a recursion in the DefinePlugin * to prevent an endless recursion * e.g.: new DefinePlugin({ - * "typeof a": "tyepof b", + * "typeof a": "typeof b", * "typeof b": "typeof a" * }); */ From 581069bb5600864c4d38e289b2cc19de6b96d4fd Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:50:05 +0000 Subject: [PATCH 060/162] spelling: uncaught --- lib/ContextModule.js | 6 +++--- lib/MainTemplate.js | 2 +- lib/node/NodeMainTemplatePlugin.js | 2 +- test/ConfigTestCases.test.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ContextModule.js b/lib/ContextModule.js index 6163225f1..bc787d074 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -373,7 +373,7 @@ function webpackAsyncContext(req) { } function webpackAsyncContextResolve(req) { // Here Promise.resolve().then() is used instead of new Promise() to prevent - // uncatched exception popping up in devtools + // uncaught exception popping up in devtools return Promise.resolve().then(function() { var id = map[req]; if(!(id + 1)) { // check for number or string @@ -410,7 +410,7 @@ function webpackAsyncContext(req) { } function webpackAsyncContextResolve(req) { // Here Promise.resolve().then() is used instead of new Promise() to prevent - // uncatched exception popping up in devtools + // uncaught exception popping up in devtools return Promise.resolve().then(function() { var id = map[req]; if(!(id + 1)) { // check for number or string @@ -547,7 +547,7 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`; getSourceForEmptyAsyncContext(id) { return `function webpackEmptyAsyncContext(req) { // Here Promise.resolve().then() is used instead of new Promise() to prevent - // uncatched exception popping up in devtools + // uncaught exception popping up in devtools return Promise.resolve().then(function() { var e = new Error('Cannot find module "' + req + '".'); e.code = 'MODULE_NOT_FOUND'; diff --git a/lib/MainTemplate.js b/lib/MainTemplate.js index bbb5e50a9..d27f5d148 100644 --- a/lib/MainTemplate.js +++ b/lib/MainTemplate.js @@ -27,7 +27,7 @@ const SyncBailHook = require("tapable").SyncBailHook; // __webpack_require__.n = compatibility get default export // __webpack_require__.h = the webpack hash // __webpack_require__.w = an object containing all installed WebAssembly.Modules keys by module id -// __webpack_require__.oe = the uncatched error handler for the webpack runtime +// __webpack_require__.oe = the uncaught error handler for the webpack runtime // __webpack_require__.nc = the script nonce module.exports = class MainTemplate extends Tapable { diff --git a/lib/node/NodeMainTemplatePlugin.js b/lib/node/NodeMainTemplatePlugin.js index c4f577ea5..4182ab0ad 100644 --- a/lib/node/NodeMainTemplatePlugin.js +++ b/lib/node/NodeMainTemplatePlugin.js @@ -43,7 +43,7 @@ module.exports = class NodeMainTemplatePlugin { return Template.asString([ source, "", - "// uncatched error handler for webpack runtime", + "// uncaught error handler for webpack runtime", `${mainTemplate.requireFn}.oe = function(err) {`, Template.indent([ "process.nextTick(function() {", diff --git a/test/ConfigTestCases.test.js b/test/ConfigTestCases.test.js index 3622b5749..0a24486ff 100644 --- a/test/ConfigTestCases.test.js +++ b/test/ConfigTestCases.test.js @@ -106,7 +106,7 @@ describe("ConfigTestCases", () => { ) ) return; - // Wait for uncatched errors to occur + // Wait for uncaught errors to occur return setTimeout(done, 200); } const statOptions = Stats.presetToOptions("verbose"); From dded403558811df864f8e48a50cf9c6ed89221f7 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Mon, 26 Feb 2018 02:50:43 +0000 Subject: [PATCH 061/162] spelling: verify --- examples/require.resolve/README.md | 4 ++-- examples/require.resolve/example.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/require.resolve/README.md b/examples/require.resolve/README.md index efb35906b..342ed1184 100644 --- a/examples/require.resolve/README.md +++ b/examples/require.resolve/README.md @@ -12,7 +12,7 @@ delete require.cache[aId]; // require module again, it should be reexecuted var a2 = require("./a"); -// vertify it +// verify it if(a == a2) throw new Error("Cache clear failed :("); ``` @@ -123,7 +123,7 @@ delete __webpack_require__.c[aId]; // require module again, it should be reexecuted var a2 = __webpack_require__(/*! ./a */ 1); -// vertify it +// verify it if(a == a2) throw new Error("Cache clear failed :("); /***/ }), diff --git a/examples/require.resolve/example.js b/examples/require.resolve/example.js index 6441689b8..9303c9036 100644 --- a/examples/require.resolve/example.js +++ b/examples/require.resolve/example.js @@ -9,5 +9,5 @@ delete require.cache[aId]; // require module again, it should be reexecuted var a2 = require("./a"); -// vertify it +// verify it if(a == a2) throw new Error("Cache clear failed :("); \ No newline at end of file From 05174aeaaf4bd5748d93b68cb05e5d0c30cda34f Mon Sep 17 00:00:00 2001 From: Naveen Jain Date: Mon, 26 Feb 2018 14:10:38 +0530 Subject: [PATCH 062/162] Added version to webpack's export property --- lib/webpack.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/webpack.js b/lib/webpack.js index 04a3b0d10..6768831ec 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -13,7 +13,7 @@ const validateSchema = require("./validateSchema"); const WebpackOptionsValidationError = require("./WebpackOptionsValidationError"); const webpackOptionsSchema = require("../schemas/WebpackOptions.json"); const RemovedPluginError = require("./RemovedPluginError"); - +const version = require("../package.json").version; const webpack = (options, callback) => { const webpackOptionsValidationErrors = validateSchema( webpackOptionsSchema, @@ -60,7 +60,7 @@ const webpack = (options, callback) => { }; exports = module.exports = webpack; - +exports.version = version; webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; webpack.WebpackOptionsApply = WebpackOptionsApply; webpack.Compiler = Compiler; From d50fa68fe1bdd8982b32dbaf86a1dd0f4f095fd0 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 26 Feb 2018 18:22:25 +0100 Subject: [PATCH 063/162] add newlines --- lib/webpack.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/webpack.js b/lib/webpack.js index 6768831ec..ed9fa612a 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -14,6 +14,7 @@ const WebpackOptionsValidationError = require("./WebpackOptionsValidationError") const webpackOptionsSchema = require("../schemas/WebpackOptions.json"); const RemovedPluginError = require("./RemovedPluginError"); const version = require("../package.json").version; + const webpack = (options, callback) => { const webpackOptionsValidationErrors = validateSchema( webpackOptionsSchema, @@ -61,6 +62,7 @@ const webpack = (options, callback) => { exports = module.exports = webpack; exports.version = version; + webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; webpack.WebpackOptionsApply = WebpackOptionsApply; webpack.Compiler = Compiler; From 8bf15740bb648d555c6032d21245bcf5e34a4056 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 26 Feb 2018 18:42:07 +0100 Subject: [PATCH 064/162] CJS fake namespace object contains exports now #6576 --- lib/ContextModule.js | 4 ++-- lib/RuntimeTemplate.js | 4 ++-- .../mjs/non-mjs-namespace-object-lazy/index.js | 8 ++++---- .../aggressive-splitting-entry/expected.txt | 4 ++-- test/statsCases/import-weak/expected.txt | 2 +- .../limit-chunk-count-plugin/expected.txt | 16 ++++++++-------- .../named-chunks-plugin-async/expected.txt | 4 ++-- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/ContextModule.js b/lib/ContextModule.js index 6163225f1..d6e66ce2a 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -269,12 +269,12 @@ class ContextModule extends Module { getReturn(type) { if (type === 1) return "module"; if (type === 2) - return 'Object.assign({/* fake namespace object */}, module, { "default": module })'; + return 'Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module })'; if (type === 0) { if (this.options.namespaceObject === "strict") { return '/* fake namespace object */ { "default": module }'; } else { - return '(typeof module === "object" && module && module.__esModule ? module : /* fake namespace object */ { "default": module })'; + return '(typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }))'; } } } diff --git a/lib/RuntimeTemplate.js b/lib/RuntimeTemplate.js index c229d364c..05554bd6c 100644 --- a/lib/RuntimeTemplate.js +++ b/lib/RuntimeTemplate.js @@ -94,7 +94,7 @@ module.exports = class RuntimeTemplate { } else { return `Object(function() { var module = ${ rawModule - }; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }())`; + }; return typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }); }())`; } } @@ -150,7 +150,7 @@ module.exports = class RuntimeTemplate { } else { getModuleFunction = `function() { ${header}var module = ${ rawModule - }; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }`; + }; return typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }); }`; } return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`; diff --git a/test/cases/mjs/non-mjs-namespace-object-lazy/index.js b/test/cases/mjs/non-mjs-namespace-object-lazy/index.js index c44f3bfb9..c9c6d829c 100644 --- a/test/cases/mjs/non-mjs-namespace-object-lazy/index.js +++ b/test/cases/mjs/non-mjs-namespace-object-lazy/index.js @@ -1,6 +1,6 @@ it("should receive a namespace object when importing commonjs", function(done) { import("./cjs").then(function(result) { - result.should.be.eql({ default: { named: "named", default: "default" } }); + result.should.be.eql({ named: "named", default: { named: "named", default: "default" } }); done(); }).catch(done); }); @@ -60,9 +60,9 @@ function promiseTest(promise, equalsTo) { it("should receive a namespace object when importing commonjs via context", function() { return Promise.all([ - promiseTest(contextCJS("one"), { default: { named: "named", default: "default" } }), + promiseTest(contextCJS("one"), { named: "named", default: { named: "named", default: "default" } }), promiseTest(contextCJS("two"), { __esModule: true, named: "named", default: "default" }), - promiseTest(contextCJS("three"), { default: { named: "named", default: "default" } }), + promiseTest(contextCJS("three"), { named: "named", default: { named: "named", default: "default" } }), promiseTest(contextCJS("null"), { default: null }) ]); }); @@ -77,7 +77,7 @@ it("should receive a namespace object when importing harmony via context", funct it("should receive a namespace object when importing mixed content via context", function() { return Promise.all([ - promiseTest(contextMixed("one"), { default: { named: "named", default: "default" } }), + promiseTest(contextMixed("one"), { named: "named", default: { named: "named", default: "default" } }), promiseTest(contextMixed("two"), { __esModule: true, named: "named", default: "default" }), promiseTest(contextMixed("three"), { named: "named", default: "default" }), promiseTest(contextMixed("null"), { default: null }) diff --git a/test/statsCases/aggressive-splitting-entry/expected.txt b/test/statsCases/aggressive-splitting-entry/expected.txt index 493e0a7a8..8cbc870fa 100644 --- a/test/statsCases/aggressive-splitting-entry/expected.txt +++ b/test/statsCases/aggressive-splitting-entry/expected.txt @@ -5,7 +5,7 @@ Child fitting: Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names fb95acf7c457672e70d0.js 1.05 KiB 0 [emitted] - a1e683753eca705a0882.js 9.92 KiB 1 [emitted] + a1e683753eca705a0882.js 9.97 KiB 1 [emitted] d43339a3d0f86c6b8d90.js 1.94 KiB 2 [emitted] 6c7fb52c5514dbfbf094.js 1.94 KiB 3 [emitted] Entrypoint main = d43339a3d0f86c6b8d90.js 6c7fb52c5514dbfbf094.js a1e683753eca705a0882.js @@ -31,7 +31,7 @@ Child content-change: Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names fb95acf7c457672e70d0.js 1.05 KiB 0 [emitted] - a1e683753eca705a0882.js 9.92 KiB 1 [emitted] + a1e683753eca705a0882.js 9.97 KiB 1 [emitted] d43339a3d0f86c6b8d90.js 1.94 KiB 2 [emitted] 6c7fb52c5514dbfbf094.js 1.94 KiB 3 [emitted] Entrypoint main = d43339a3d0f86c6b8d90.js 6c7fb52c5514dbfbf094.js a1e683753eca705a0882.js diff --git a/test/statsCases/import-weak/expected.txt b/test/statsCases/import-weak/expected.txt index 89db3bb27..921e5d9a7 100644 --- a/test/statsCases/import-weak/expected.txt +++ b/test/statsCases/import-weak/expected.txt @@ -3,7 +3,7 @@ Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names 0.js 149 bytes 0 [emitted] -entry.js 7.63 KiB 1 [emitted] entry +entry.js 7.79 KiB 1 [emitted] entry Entrypoint entry = entry.js [0] ./modules/b.js 22 bytes {0} [built] [1] ./entry.js 120 bytes {1} [built] diff --git a/test/statsCases/limit-chunk-count-plugin/expected.txt b/test/statsCases/limit-chunk-count-plugin/expected.txt index 5062c302f..e7654d94f 100644 --- a/test/statsCases/limit-chunk-count-plugin/expected.txt +++ b/test/statsCases/limit-chunk-count-plugin/expected.txt @@ -4,7 +4,7 @@ Child 1 chunks: Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names - bundle.js 5.52 KiB 0 [emitted] main + bundle.js 5.68 KiB 0 [emitted] main Entrypoint main = bundle.js chunk {0} bundle.js (main) 191 bytes <{0}> >{0}< [entry] [rendered] [0] ./index.js 73 bytes {0} [built] @@ -17,9 +17,9 @@ Child 2 chunks: Hash: f90c7b21ae5c6e853a0d Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT - Asset Size Chunks Chunk Names - 0.bundle.js 912 bytes 0 [emitted] - bundle.js 7.14 KiB 1 [emitted] main + Asset Size Chunks Chunk Names + 0.bundle.js 1 KiB 0 [emitted] + bundle.js 7.19 KiB 1 [emitted] main Entrypoint main = bundle.js chunk {0} 0.bundle.js 118 bytes <{0}> <{1}> >{0}< [rendered] [0] ./d.js 22 bytes {0} [built] @@ -34,9 +34,9 @@ Child 3 chunks: Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names - 0.bundle.js 774 bytes 0 [emitted] + 0.bundle.js 886 bytes 0 [emitted] 1.bundle.js 245 bytes 1 [emitted] - bundle.js 7.14 KiB 2 [emitted] main + bundle.js 7.19 KiB 2 [emitted] main Entrypoint main = bundle.js chunk {0} 0.bundle.js 74 bytes <{0}> <{2}> >{0}< >{1}< [rendered] [0] ./d.js 22 bytes {0} [built] @@ -54,8 +54,8 @@ Child 4 chunks: Asset Size Chunks Chunk Names 0.bundle.js 236 bytes 0 [emitted] 1.bundle.js 245 bytes 1 [emitted] - 2.bundle.js 603 bytes 2 [emitted] - bundle.js 7.14 KiB 3 [emitted] main + 2.bundle.js 715 bytes 2 [emitted] + bundle.js 7.19 KiB 3 [emitted] main Entrypoint main = bundle.js chunk {0} 0.bundle.js 44 bytes <{2}> <{3}> [rendered] [0] ./d.js 22 bytes {0} [built] diff --git a/test/statsCases/named-chunks-plugin-async/expected.txt b/test/statsCases/named-chunks-plugin-async/expected.txt index 78f3b1805..f5d8b300c 100644 --- a/test/statsCases/named-chunks-plugin-async/expected.txt +++ b/test/statsCases/named-chunks-plugin-async/expected.txt @@ -2,9 +2,9 @@ Hash: c5b0089a4015e8744f8e Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Asset Size Chunks Chunk Names -chunk-containing-__a_js.js 453 bytes chunk-containing-__a_js [emitted] +chunk-containing-__a_js.js 509 bytes chunk-containing-__a_js [emitted] chunk-containing-__b_js.js 173 bytes chunk-containing-__b_js [emitted] - entry.js 7.17 KiB entry [emitted] entry + entry.js 7.28 KiB entry [emitted] entry Entrypoint entry = entry.js [0] ./modules/b.js 22 bytes {chunk-containing-__b_js} [built] [1] ./modules/a.js 37 bytes {chunk-containing-__a_js} [built] From e7aba18ed502f18318905036c2525f590b38ce25 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 26 Feb 2018 20:22:58 +0100 Subject: [PATCH 065/162] fix incorrect optimization bailout messages fixes #6570 --- lib/optimize/ModuleConcatenationPlugin.js | 21 ++++++-------- .../scope-hoisting-bailouts/concatenated.js | 1 + .../scope-hoisting-bailouts/concatenated1.js | 1 + .../scope-hoisting-bailouts/concatenated2.js | 2 ++ .../scope-hoisting-bailouts/expected.txt | 28 ++++++++++++------- .../scope-hoisting-bailouts/index.js | 1 + .../scope-hoisting-bailouts/webpack.config.js | 1 + 7 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 test/statsCases/scope-hoisting-bailouts/concatenated.js create mode 100644 test/statsCases/scope-hoisting-bailouts/concatenated1.js create mode 100644 test/statsCases/scope-hoisting-bailouts/concatenated2.js diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index 4b9f5e3d8..c591c0980 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -375,21 +375,16 @@ class ModuleConcatenationPlugin { } } - // Eagerly try to add imports too if possible - for (const imp of this.getImports(module)) { - const problem = this.tryToAdd( - testConfig, - imp, - possibleModules, - failureCache - ); - if (problem) { - config.addWarning(module, problem); - } - } - // Commit experimental changes config.set(testConfig); + + // Eagerly try to add imports too if possible + for (const imp of this.getImports(module)) { + const problem = this.tryToAdd(config, imp, possibleModules, failureCache); + if (problem) { + config.addWarning(imp, problem); + } + } return null; } } diff --git a/test/statsCases/scope-hoisting-bailouts/concatenated.js b/test/statsCases/scope-hoisting-bailouts/concatenated.js new file mode 100644 index 000000000..1b372f8c0 --- /dev/null +++ b/test/statsCases/scope-hoisting-bailouts/concatenated.js @@ -0,0 +1 @@ +import "./concatenated1"; diff --git a/test/statsCases/scope-hoisting-bailouts/concatenated1.js b/test/statsCases/scope-hoisting-bailouts/concatenated1.js new file mode 100644 index 000000000..c5e494f12 --- /dev/null +++ b/test/statsCases/scope-hoisting-bailouts/concatenated1.js @@ -0,0 +1 @@ +import { x } from "./concatenated2"; diff --git a/test/statsCases/scope-hoisting-bailouts/concatenated2.js b/test/statsCases/scope-hoisting-bailouts/concatenated2.js new file mode 100644 index 000000000..eb580d946 --- /dev/null +++ b/test/statsCases/scope-hoisting-bailouts/concatenated2.js @@ -0,0 +1,2 @@ +import { y } from "external"; +export var x = y; diff --git a/test/statsCases/scope-hoisting-bailouts/expected.txt b/test/statsCases/scope-hoisting-bailouts/expected.txt index 9a7291212..f61b7e1bb 100644 --- a/test/statsCases/scope-hoisting-bailouts/expected.txt +++ b/test/statsCases/scope-hoisting-bailouts/expected.txt @@ -1,21 +1,29 @@ -Hash: 2f9dacd48c09c3072b04 +Hash: 123228577e0595ae0a8e Time: Xms Built at: Thu Jan 01 1970 00:00:00 GMT Entrypoint index = index.js Entrypoint entry = entry.js - [0] ./entry.js 32 bytes {0} {1} [built] + [0] ./entry.js 32 bytes {1} {2} [built] ModuleConcatenation bailout: Module is an entry point - [1] ./ref-from-cjs.js 45 bytes {0} [built] + [1] ./ref-from-cjs.js 45 bytes {1} [built] ModuleConcatenation bailout: Module is referenced from these modules with unsupported syntax: ./cjs.js (referenced with cjs require) - [2] ./index.js 150 bytes {0} [built] - ModuleConcatenation bailout: Module is an entry point - [3] ./cjs.js 59 bytes {0} [built] + [2] external "external" 42 bytes {1} [built] ModuleConcatenation bailout: Module is not an ECMAScript module - [4] ./eval.js 35 bytes {0} [built] + [3] ./concatenated.js + 2 modules 116 bytes {0} [built] + ModuleConcatenation bailout: Cannot concat with external "external" (<- Module is not an ECMAScript module) + | ./concatenated.js 26 bytes [built] + | ModuleConcatenation bailout: Module is referenced from these modules with unsupported syntax: ./index.js (referenced with import()) + | ./concatenated1.js 37 bytes [built] + | ./concatenated2.js 48 bytes [built] + [4] ./index.js 176 bytes {1} [built] + ModuleConcatenation bailout: Module is an entry point + [5] ./cjs.js 59 bytes {1} [built] + ModuleConcatenation bailout: Module is not an ECMAScript module + [6] ./eval.js 35 bytes {1} [built] ModuleConcatenation bailout: Module uses eval() - [5] ./injected-vars.js 40 bytes {0} [built] + [7] ./injected-vars.js 40 bytes {1} [built] ModuleConcatenation bailout: Module uses injected variables (__dirname, __filename) - [6] ./module-id.js 26 bytes {0} [built] + [8] ./module-id.js 26 bytes {1} [built] ModuleConcatenation bailout: Module uses module.id - [7] ./module-loaded.js 30 bytes {0} [built] + [9] ./module-loaded.js 30 bytes {1} [built] ModuleConcatenation bailout: Module uses module.loaded \ No newline at end of file diff --git a/test/statsCases/scope-hoisting-bailouts/index.js b/test/statsCases/scope-hoisting-bailouts/index.js index 26d1840f9..4b47535df 100644 --- a/test/statsCases/scope-hoisting-bailouts/index.js +++ b/test/statsCases/scope-hoisting-bailouts/index.js @@ -5,3 +5,4 @@ import "./injected-vars"; import "./module-id"; import "./module-loaded"; import "./ref-from-cjs"; +import("./concatenated"); diff --git a/test/statsCases/scope-hoisting-bailouts/webpack.config.js b/test/statsCases/scope-hoisting-bailouts/webpack.config.js index 12885b3a6..217a56fcc 100644 --- a/test/statsCases/scope-hoisting-bailouts/webpack.config.js +++ b/test/statsCases/scope-hoisting-bailouts/webpack.config.js @@ -8,6 +8,7 @@ module.exports = { output: { filename: "[name].js" }, + externals: ["external"], stats: { assets: false, optimizationBailout: true From 5044762c846a3a83a208853e48785a293fe9ef7d Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 26 Feb 2018 21:11:03 +0100 Subject: [PATCH 066/162] 4.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ea24a43c..9679b8baf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "4.0.0", + "version": "4.0.1", "author": "Tobias Koppers @sokra", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "license": "MIT", From 1ab9fdb8b005c0363d4d1f50fd3190fa90bb45fb Mon Sep 17 00:00:00 2001 From: Naveen Jain Date: Tue, 27 Feb 2018 06:02:09 +0530 Subject: [PATCH 067/162] Fixed Parser so that this Expression can work with ProvidePlugin --- lib/Parser.js | 2 +- test/configCases/plugins/provide-plugin/index.js | 4 ++++ test/configCases/plugins/provide-plugin/webpack.config.js | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 7ca4d5426..30c7f4b81 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -2008,7 +2008,7 @@ class Parser extends Tapable { free = true; exprName.push(this.scope.renames.get("this")); } else if (expr.type === "ThisExpression") { - free = false; + free = this.scope.topLevelScope; exprName.push("this"); } else { return null; diff --git a/test/configCases/plugins/provide-plugin/index.js b/test/configCases/plugins/provide-plugin/index.js index 5f1c9a45d..7bfad58c0 100644 --- a/test/configCases/plugins/provide-plugin/index.js +++ b/test/configCases/plugins/provide-plugin/index.js @@ -16,6 +16,10 @@ it("should provide a module for a nested var within a IIFE's argument", function }(process)); }); +it("should provide a module for thisExpression", () => { + (this.aaa).should.be.eql("aaa"); +}); + it("should provide a module for a nested var within a IIFE's this", function() { (function() { (this.env.NODE_ENV).should.be.eql("development"); diff --git a/test/configCases/plugins/provide-plugin/webpack.config.js b/test/configCases/plugins/provide-plugin/webpack.config.js index cba942cab..05b97a8af 100644 --- a/test/configCases/plugins/provide-plugin/webpack.config.js +++ b/test/configCases/plugins/provide-plugin/webpack.config.js @@ -9,7 +9,8 @@ module.exports = { es2015: "./harmony", es2015_name: ["./harmony", "default"], es2015_alias: ["./harmony", "alias"], - es2015_year: ["./harmony", "year"] + es2015_year: ["./harmony", "year"], + "this.aaa": "./aaa" }) ] }; From 95adc934528a04ba6df39cd171a35e4c1d180682 Mon Sep 17 00:00:00 2001 From: kvrlk <36900613+kvrlk@users.noreply.github.com> Date: Tue, 27 Feb 2018 22:31:58 +0200 Subject: [PATCH 068/162] tests --- test/Validation.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Validation.test.js b/test/Validation.test.js index 1d40796fb..bfdd24ed3 100644 --- a/test/Validation.test.js +++ b/test/Validation.test.js @@ -203,7 +203,7 @@ describe("Validation", () => { "loader?, module?, name?, node?, output?, optimization?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, " + "recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, stats?, target?, watch?, watchOptions? }", " For typos: please correct them.", - " For loader options: webpack 2 no longer allows custom properties in configuration.", + " For loader options: webpack since version 2 no longer allows custom properties in configuration.", " Loaders should be updated to allow passing options via loader options in module.rules.", " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:", " plugins: [", From 05e3ae8b306084ab41753fea1e3a13f45d27c44a Mon Sep 17 00:00:00 2001 From: kvrlk <36900613+kvrlk@users.noreply.github.com> Date: Tue, 27 Feb 2018 22:32:51 +0200 Subject: [PATCH 069/162] Fixed messages --- lib/WebpackOptionsValidationError.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index d2d59deeb..ce6749b71 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -155,7 +155,7 @@ class WebpackOptionsValidationError extends WebpackError { case "debug": return ( `${baseMessage}\n` + - "The 'debug' property was removed in webpack 2.\n" + + "The 'debug' property was removed since webpack 2.\n" + "Loaders should be updated to allow passing this option via loader options in module.rules.\n" + "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" + "plugins: [\n" + @@ -169,7 +169,7 @@ class WebpackOptionsValidationError extends WebpackError { baseMessage + "\n" + "For typos: please correct them.\n" + - "For loader options: webpack 2 no longer allows custom properties in configuration.\n" + + "For loader options: webpack since version 2 no longer allows custom properties in configuration.\n" + " Loaders should be updated to allow passing options via loader options in module.rules.\n" + " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:\n" + " plugins: [\n" + From ea33a974c02f813f7cae40bd20c0c177ce88a11e Mon Sep 17 00:00:00 2001 From: kvrlk <36900613+kvrlk@users.noreply.github.com> Date: Tue, 27 Feb 2018 22:40:48 +0200 Subject: [PATCH 070/162] Fixed --- lib/WebpackOptionsValidationError.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index ce6749b71..0a9042484 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -169,7 +169,7 @@ class WebpackOptionsValidationError extends WebpackError { baseMessage + "\n" + "For typos: please correct them.\n" + - "For loader options: webpack since version 2 no longer allows custom properties in configuration.\n" + + "For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.\n" + " Loaders should be updated to allow passing options via loader options in module.rules.\n" + " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:\n" + " plugins: [\n" + From 97c9a6d84b16d56dfc4058ed2e1028ad3d148206 Mon Sep 17 00:00:00 2001 From: kvrlk <36900613+kvrlk@users.noreply.github.com> Date: Tue, 27 Feb 2018 22:41:31 +0200 Subject: [PATCH 071/162] fix --- test/Validation.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Validation.test.js b/test/Validation.test.js index bfdd24ed3..8b70c8ab3 100644 --- a/test/Validation.test.js +++ b/test/Validation.test.js @@ -203,7 +203,7 @@ describe("Validation", () => { "loader?, module?, name?, node?, output?, optimization?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, " + "recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, stats?, target?, watch?, watchOptions? }", " For typos: please correct them.", - " For loader options: webpack since version 2 no longer allows custom properties in configuration.", + " For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.", " Loaders should be updated to allow passing options via loader options in module.rules.", " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:", " plugins: [", From 9f37b499bfd4a59ba8083dc06616fb0976459228 Mon Sep 17 00:00:00 2001 From: Brent Wilton Date: Wed, 28 Feb 2018 11:46:12 +1300 Subject: [PATCH 072/162] improve performance of ModuleConcatenationPlugin for loop --- lib/optimize/ModuleConcatenationPlugin.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index c591c0980..e7c7fc946 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -281,9 +281,12 @@ class ModuleConcatenationPlugin { for (const reason of newModule.reasons) { reason.dependency.module = newModule; } - for (const dep of newModule.dependencies) { + for (let i = 0; i < newModule.dependencies.length; i++) { + let dep = newModule.dependencies[i]; if (dep.module) { - for (const reason of dep.module.reasons) { + let reasons = dep.module.reasons; + for (let j = 0; j < reasons.length; j++) { + let reason = reasons[j]; if (reason.dependency === dep) reason.module = newModule; } } From 8d0d2b16951b40e3412c4236b5dbb85e3ff126b9 Mon Sep 17 00:00:00 2001 From: kvrlk <36900613+kvrlk@users.noreply.github.com> Date: Wed, 28 Feb 2018 18:12:06 +0200 Subject: [PATCH 073/162] rollback edit --- lib/WebpackOptionsValidationError.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index 0a9042484..851bbb5a6 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -155,7 +155,7 @@ class WebpackOptionsValidationError extends WebpackError { case "debug": return ( `${baseMessage}\n` + - "The 'debug' property was removed since webpack 2.\n" + + "The 'debug' property was removed in webpack 2.\n" + "Loaders should be updated to allow passing this option via loader options in module.rules.\n" + "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" + "plugins: [\n" + From b8155970dba6bfc5f9360f40bd429f50cdb3a436 Mon Sep 17 00:00:00 2001 From: Clark Du Date: Fri, 2 Mar 2018 02:17:46 +0800 Subject: [PATCH 074/162] fix: module assets is in buildInfo --- lib/Stats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Stats.js b/lib/Stats.js index d7a4cb405..5ec4c4b31 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -417,7 +417,7 @@ class Stats { optional: module.optional, prefetched: module.prefetched, chunks: Array.from(module.chunksIterable, chunk => chunk.id), - assets: Object.keys(module.assets || {}), + assets: Object.keys(module.buildInfo.assets || {}), issuer: module.issuer && module.issuer.identifier(), issuerId: module.issuer && module.issuer.id, issuerName: From fc0b327d82500e869a426888d5778966632c3abe Mon Sep 17 00:00:00 2001 From: Jason Milloff Date: Thu, 1 Mar 2018 16:07:24 -0500 Subject: [PATCH 075/162] Fix #6634 --- lib/WebpackOptionsDefaulter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index 3c7b1f83a..e1a82ad86 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -128,6 +128,8 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { } }); this.set("output.devtoolNamespace", "make", options => { + if (Array.isArray(options.output.library)) + return [].concat(options.output.library).join("."); return options.output.library || ""; }); this.set("output.libraryTarget", "var"); From 17d03c1b246df8c85c31a49cad726548ac8eca93 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Thu, 1 Mar 2018 16:08:49 -0800 Subject: [PATCH 076/162] defaults: set source map option for UglifyJs to true if SourceMapDevToolPlugin exists #6627 --- lib/WebpackOptionsDefaulter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index 3c7b1f83a..c46b2bddb 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -264,10 +264,14 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { apply: compiler => { // Lazy load the uglifyjs plugin const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); + const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); new UglifyJsPlugin({ cache: true, parallel: true, - sourceMap: options.devtool && /source-?map/.test(options.devtool) + sourceMap: + (options.devtool && /source-?map/.test(options.devtool)) || + (options.plugins && + options.plugins.some(p => p instanceof SourceMapDevToolPlugin)) }).apply(compiler); } } From 39095efc340fdee70bef27a89ef88d7e67db5782 Mon Sep 17 00:00:00 2001 From: Brent Wilton Date: Fri, 2 Mar 2018 14:08:26 +1300 Subject: [PATCH 077/162] add todo for ModuleConcatenationPlugin for loop bugfix --- lib/optimize/ModuleConcatenationPlugin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index e7c7fc946..08e2a7641 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -281,6 +281,10 @@ class ModuleConcatenationPlugin { for (const reason of newModule.reasons) { reason.dependency.module = newModule; } + // TODO: remove when LTS node version contains fixed v8 version + // @see https://github.com/webpack/webpack/pull/6613 + // Turbofan does not correctly inline for-of loops with polymorphic input arrays. + // Work around issue by using a standard for loop and assigning dep.module.reasons for (let i = 0; i < newModule.dependencies.length; i++) { let dep = newModule.dependencies[i]; if (dep.module) { From 3a41ca4ee223a93803cb9e0cfc27e2306699f154 Mon Sep 17 00:00:00 2001 From: zacanger Date: Thu, 1 Mar 2018 17:09:01 -0700 Subject: [PATCH 078/162] Fix #6644 --- lib/optimize/SplitChunksPlugin.js | 2 +- test/configCases/split-chunks/no-options/a.js | 1 + test/configCases/split-chunks/no-options/index.js | 6 ++++++ .../split-chunks/no-options/test.config.js | 5 +++++ .../split-chunks/no-options/webpack.config.js | 13 +++++++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/configCases/split-chunks/no-options/a.js create mode 100644 test/configCases/split-chunks/no-options/index.js create mode 100644 test/configCases/split-chunks/no-options/test.config.js create mode 100644 test/configCases/split-chunks/no-options/webpack.config.js diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 9cbd34087..f971534ed 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -83,7 +83,7 @@ module.exports = class SplitChunksPlugin { this.options = SplitChunksPlugin.normalizeOptions(options); } - static normalizeOptions(options) { + static normalizeOptions(options = {}) { return { chunks: options.chunks || "all", minSize: options.minSize || 0, diff --git a/test/configCases/split-chunks/no-options/a.js b/test/configCases/split-chunks/no-options/a.js new file mode 100644 index 000000000..6cd1d0075 --- /dev/null +++ b/test/configCases/split-chunks/no-options/a.js @@ -0,0 +1 @@ +module.exports = "a"; diff --git a/test/configCases/split-chunks/no-options/index.js b/test/configCases/split-chunks/no-options/index.js new file mode 100644 index 000000000..b5158af81 --- /dev/null +++ b/test/configCases/split-chunks/no-options/index.js @@ -0,0 +1,6 @@ +require("should"); + +it("should run", function() { + var a = require("./a"); + a.should.be.eql("a"); +}); diff --git a/test/configCases/split-chunks/no-options/test.config.js b/test/configCases/split-chunks/no-options/test.config.js new file mode 100644 index 000000000..6f3aaf93f --- /dev/null +++ b/test/configCases/split-chunks/no-options/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function(i, options) { + return ["vendor.js", "main.js"]; + } +}; diff --git a/test/configCases/split-chunks/no-options/webpack.config.js b/test/configCases/split-chunks/no-options/webpack.config.js new file mode 100644 index 000000000..16fb53733 --- /dev/null +++ b/test/configCases/split-chunks/no-options/webpack.config.js @@ -0,0 +1,13 @@ +const SplitChunksPlugin = require("../../../../lib/optimize/SplitChunksPlugin"); + +module.exports = { + entry: { + vendor: ["./a"], + main: "./index" + }, + target: "web", + output: { + filename: "[name].js" + }, + plugins: [new SplitChunksPlugin()] +}; From a2fd80eb57b073fb8952fa0f04053ff6382678e4 Mon Sep 17 00:00:00 2001 From: Chang Wang Date: Thu, 1 Mar 2018 21:30:03 -0500 Subject: [PATCH 079/162] Update downloads badge to point to graph of downloads --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3b807d81..d2b0b62a9 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![licenses][licenses]][licenses-url]
- + From 325038d3fb6e1dc724a84257f1d20aeccfafa1ee Mon Sep 17 00:00:00 2001 From: Florent Cailhol Date: Fri, 2 Mar 2018 10:02:53 +0100 Subject: [PATCH 080/162] Update watchpack to 1.5.0 --- package.json | 2 +- yarn.lock | 240 ++++++++++++++------------------------------------- 2 files changed, 67 insertions(+), 175 deletions(-) diff --git a/package.json b/package.json index 9679b8baf..384dd095e 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "schema-utils": "^0.4.2", "tapable": "^1.0.0", "uglifyjs-webpack-plugin": "^1.1.1", - "watchpack": "^1.4.0", + "watchpack": "^1.5.0", "webpack-sources": "^1.0.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 745dc02aa..d03d60ae8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -134,12 +134,12 @@ ansi-styles@^3.1.0: dependencies: color-convert "^1.9.0" -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" + micromatch "^3.1.4" + normalize-path "^2.1.1" aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" @@ -158,17 +158,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" -arr-flatten@^1.0.1, arr-flatten@^1.1.0: +arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" @@ -190,10 +184,6 @@ array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -248,12 +238,6 @@ async@1.x, async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.2: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - dependencies: - lodash "^4.14.0" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -381,15 +365,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -braces@^2.3.1: +braces@^2.3.0, braces@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" dependencies: @@ -595,18 +571,21 @@ chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" -chokidar@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" +chokidar@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7" dependencies: - anymatch "^1.3.0" + anymatch "^2.0.0" async-each "^1.0.0" - glob-parent "^2.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" inherits "^2.0.1" is-binary-path "^1.0.0" - is-glob "^2.0.0" + is-glob "^4.0.0" + normalize-path "^2.1.1" path-is-absolute "^1.0.0" readdirp "^2.0.0" + upath "^1.0.0" optionalDependencies: fsevents "^1.0.0" @@ -1400,12 +1379,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -1418,12 +1391,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - express@~4.13.1: version "4.13.4" resolved "https://registry.yarnpkg.com/express/-/express-4.13.4.tgz#3c0b76f3c77590c8345739061ec0bd3ba067ec24" @@ -1479,12 +1446,6 @@ external-editor@^2.0.4: iconv-lite "^0.4.17" tmp "^0.0.33" -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -1558,20 +1519,6 @@ file-loader@^1.1.6: loader-utils "^1.0.2" schema-utils "^0.3.0" -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1624,16 +1571,10 @@ flush-write-stream@^1.0.0: inherits "^2.0.1" readable-stream "^2.0.4" -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -1759,18 +1700,12 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" + is-glob "^3.1.0" + path-dirname "^1.0.0" glob@7.1.1: version "7.1.1" @@ -2154,16 +2089,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -2174,9 +2099,9 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" is-fullwidth-code-point@^1.0.0: version "1.0.0" @@ -2188,11 +2113,17 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" dependencies: - is-extglob "^1.0.0" + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" is-my-json-valid@^2.12.4: version "2.17.1" @@ -2203,12 +2134,6 @@ is-my-json-valid@^2.12.4: jsonpointer "^4.0.0" xtend "^4.0.0" -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -2251,14 +2176,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - is-promise@^2.0.0, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -2631,7 +2548,7 @@ lodash@^3.10.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.14.0, lodash@^4.17.4, lodash@^4.3.0: +lodash@^4.17.4, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2710,23 +2627,23 @@ methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micromatch@^2.1.5: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" +micromatch@^3.1.4: + version "3.1.9" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.9.tgz#15dc93175ae39e52e93087847096effc73efcf89" dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" micromatch@^3.1.8: version "3.1.8" @@ -2978,7 +2895,7 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-path@^2.0.0, normalize-path@^2.0.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: @@ -3036,13 +2953,6 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -3148,15 +3058,6 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - parseurl@~1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" @@ -3169,6 +3070,10 @@ path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -3503,10 +3408,6 @@ prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - prettier@^1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8" @@ -3636,13 +3537,6 @@ querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" @@ -3735,12 +3629,6 @@ regenerate@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -4657,6 +4545,10 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +upath@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d" + urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -4734,13 +4626,13 @@ void-elements@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" -watchpack@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" +watchpack@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.5.0.tgz#231e783af830a22f8966f65c4c4bacc814072eed" dependencies: - async "^2.1.2" - chokidar "^1.7.0" + chokidar "^2.0.2" graceful-fs "^4.1.2" + neo-async "^2.5.0" webpack-dev-middleware@^1.9.0: version "1.12.2" From ecb65aa75a7c364a50cae938b53a2cf7bcefc32a Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Fri, 2 Mar 2018 10:14:25 +0100 Subject: [PATCH 081/162] allow to configure filename for splitted chunks #6598 --- lib/JavascriptModulesPlugin.js | 5 ++++- lib/optimize/SplitChunksPlugin.js | 17 +++++++++++++++++ schemas/WebpackOptions.json | 10 ++++++++++ .../split-chunks-filename/index.js | 9 +++++++++ .../node_modules/test.js | 1 + .../split-chunks-filename/webpack.config.js | 19 +++++++++++++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/configCases/filename-template/split-chunks-filename/index.js create mode 100644 test/configCases/filename-template/split-chunks-filename/node_modules/test.js create mode 100644 test/configCases/filename-template/split-chunks-filename/webpack.config.js diff --git a/lib/JavascriptModulesPlugin.js b/lib/JavascriptModulesPlugin.js index 6394f465f..c71c6c61b 100644 --- a/lib/JavascriptModulesPlugin.js +++ b/lib/JavascriptModulesPlugin.js @@ -100,7 +100,10 @@ class JavascriptModulesPlugin { const moduleTemplates = options.moduleTemplates; const dependencyTemplates = options.dependencyTemplates; - const filenameTemplate = outputOptions.chunkFilename; + let filenameTemplate; + if (chunk.filenameTemplate) + filenameTemplate = chunk.filenameTemplate; + else filenameTemplate = outputOptions.chunkFilename; result.push({ render: () => diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 9cbd34087..96e3ca750 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -91,6 +91,7 @@ module.exports = class SplitChunksPlugin { maxAsyncRequests: options.maxAsyncRequests || 1, maxInitialRequests: options.maxInitialRequests || 1, getName: SplitChunksPlugin.normalizeName(options.name) || (() => {}), + filename: options.filename || undefined, getCacheGroups: SplitChunksPlugin.normalizeCacheGroups( options.cacheGroups ) @@ -169,6 +170,7 @@ module.exports = class SplitChunksPlugin { minChunks: option.minChunks, maxAsyncRequests: option.maxAsyncRequests, maxInitialRequests: option.maxInitialRequests, + filename: option.filename, reuseExistingChunk: option.reuseExistingChunk }); } @@ -277,6 +279,10 @@ module.exports = class SplitChunksPlugin { cacheGroupSource.getName !== undefined ? cacheGroupSource.getName : this.options.getName, + filename: + cacheGroupSource.filename !== undefined + ? cacheGroupSource.filename + : this.options.filename, reuseExistingChunk: cacheGroupSource.reuseExistingChunk }; // For all combination of chunk selection @@ -439,6 +445,17 @@ module.exports = class SplitChunksPlugin { newChunk.entryModule = undefined; } } + if (item.cacheGroup.filename) { + if (!newChunk.isOnlyInitial()) { + throw new Error( + "SplitChunksPlugin: You are trying to set a filename for a chunk which is (also) loaded on demand. " + + "The runtime can only handle loading of chunks which match the chunkFilename schema. " + + "Using a custom filename would fail at runtime. " + + `(cache group: ${item.cacheGroup.key})` + ); + } + newChunk.filenameTemplate = item.cacheGroup.filename; + } if (!isReused) { // Add all modules to the new chunk for (const module of item.modules) { diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index 62b8ee077..d0287f3c4 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -1377,6 +1377,11 @@ } ] }, + "filename": { + "description": "Sets the template for the filename for created chunks (Only works for initial chunks)", + "type": "string", + "minLength": 1 + }, "cacheGroups": { "description": "Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks)", "type": "object", @@ -1468,6 +1473,11 @@ "type": "string" } ] + }, + "filename": { + "description": "Sets the template for the filename for created chunks (Only works for initial chunks)", + "type": "string", + "minLength": 1 } } } diff --git a/test/configCases/filename-template/split-chunks-filename/index.js b/test/configCases/filename-template/split-chunks-filename/index.js new file mode 100644 index 000000000..66eba381f --- /dev/null +++ b/test/configCases/filename-template/split-chunks-filename/index.js @@ -0,0 +1,9 @@ +it("should create a vendor file", function() { + var fs = require("fs"); + var path = require("path"); + if(!fs.existsSync(path.join(__dirname, "vendor.js"))) + throw new Error("vendor.js file was not created"); +}); + +require.include("test"); + diff --git a/test/configCases/filename-template/split-chunks-filename/node_modules/test.js b/test/configCases/filename-template/split-chunks-filename/node_modules/test.js new file mode 100644 index 000000000..8b1a39374 --- /dev/null +++ b/test/configCases/filename-template/split-chunks-filename/node_modules/test.js @@ -0,0 +1 @@ +// empty diff --git a/test/configCases/filename-template/split-chunks-filename/webpack.config.js b/test/configCases/filename-template/split-chunks-filename/webpack.config.js new file mode 100644 index 000000000..580604fe0 --- /dev/null +++ b/test/configCases/filename-template/split-chunks-filename/webpack.config.js @@ -0,0 +1,19 @@ +module.exports = { + mode: "development", + node: { + __dirname: false, + __filename: false + }, + optimization: { + splitChunks: { + cacheGroups: { + vendor: { + test: /node_modules/, + chunks: "initial", + filename: "vendor.js", + enforce: true + } + } + } + } +}; From c03293afd7a59d77897f6b5da6bad64f40d15bcd Mon Sep 17 00:00:00 2001 From: Clark Du Date: Fri, 2 Mar 2018 23:49:15 +0800 Subject: [PATCH 082/162] Add modules assets test --- test/statsCases/modules-assets/expected.txt | 16 ++++++++++++++++ test/statsCases/modules-assets/index.js | 1 + .../modules-assets/node_modules/a/1.png | Bin 0 -> 21499 bytes .../modules-assets/node_modules/a/index.js | 1 + .../modules-assets/webpack.config.js | 17 +++++++++++++++++ 5 files changed, 35 insertions(+) create mode 100644 test/statsCases/modules-assets/expected.txt create mode 100644 test/statsCases/modules-assets/index.js create mode 100644 test/statsCases/modules-assets/node_modules/a/1.png create mode 100644 test/statsCases/modules-assets/node_modules/a/index.js create mode 100644 test/statsCases/modules-assets/webpack.config.js diff --git a/test/statsCases/modules-assets/expected.txt b/test/statsCases/modules-assets/expected.txt new file mode 100644 index 000000000..3599c10a1 --- /dev/null +++ b/test/statsCases/modules-assets/expected.txt @@ -0,0 +1,16 @@ +Hash: e6165e79d5ae833a8859 +Time: Xms +Built at: Thu Jan 01 1970 00:00:00 GMT + Asset Size Chunks Chunk Names +155613d841c408f2a34b9c81cdfd3e8c.png 37.7 KiB [emitted] + 0.js 607 bytes 0 [emitted] + main.js 6.76 KiB 1 [emitted] main +Entrypoint main = main.js +chunk {0} 0.js 99 bytes <{1}> [rendered] + [0] ./node_modules/a/1.png 82 bytes {0} [built] + [1] ./node_modules/a/index.js 17 bytes {0} [built] +chunk {1} main.js (main) 12 bytes >{0}< [entry] [rendered] + [2] ./index.js 12 bytes {1} [built] + [0] ./node_modules/a/1.png 82 bytes {0} [built] + [1] ./node_modules/a/index.js 17 bytes {0} [built] + [2] ./index.js 12 bytes {1} [built] \ No newline at end of file diff --git a/test/statsCases/modules-assets/index.js b/test/statsCases/modules-assets/index.js new file mode 100644 index 000000000..06de56f41 --- /dev/null +++ b/test/statsCases/modules-assets/index.js @@ -0,0 +1 @@ +import('a') diff --git a/test/statsCases/modules-assets/node_modules/a/1.png b/test/statsCases/modules-assets/node_modules/a/1.png new file mode 100644 index 0000000000000000000000000000000000000000..48924276b77832ff5d27ee87f16a98ec8174a746 GIT binary patch literal 21499 zcmeFYRZv__7cM+FK>`G~;I6?fxCMe+aCZo9K?Zl%;2zw9JA}aC5ZnpwZiCI7$@^9P zcmL(NI~P;6d)MyOtCw^yc_vC#Sq>A81PuTHV1AO9RtEs!0$@K^RAktjYodk-004vD zR!U0slav&ts;iTgt%D^1ARm>cgQA%-LXg)>OGQGjG@CZCHt%7>=OO3uU@TYoA>hHv zY7zr*+(6bKKsXPeR7vHCLPt0IQS#%%CoDKLoBV6qiQ7xe8a$-G}i@%gA0TTvnR6m9AR)x;)%Ky{y-zo?OzlzjMm zvT|>aU%A2x9U@K7{veu)3QGtQ?tS|48}msH{c$D{Of{awXg1=gU?~_C6e7xx20o?A zSCR=1wV+dJsuBN=huJ{#+pARY3MYhbDh9Fokcu>lRe6#aazHek8al+}$ay1jq-ylN zReU)9{qLm5;85p11BZ7R#eaXGyYLxjy%YSM0>XN$wjYLnBNG+!(%|Y6pt@G@%IEU+ zwBX~y_!MT!i4xV`yak#NMj{)E6Wi3i*fwBqrI%0>E)EhJBi` zZ(;=zo9g&5oC@V60uCi1B%R4BD!iC32&78$!X!lKIuWKMdY=+sAzDHcjvW%U^;@+F zvo_&*OVpe81-WlO)_2=Ts;g%iHxGN|4c41Q)Z9@0l(4~MitpSKc!!~6QYejMU{T?< zci%h)LY$2cDV~Oi+eGU@hNdOrYZODCAuAW{qv6~T?J)^s3pp-@_Y!X@^`XP!6WSAw zOEF#Qn~RboEaq)`)mupvHzxi%V((9B0-Amkn4;7-F1HmIR`H9?~ypvoED?Z3Cz_iD&vHnM7nPRAJu%8vBNX_Ht zmdF#%=%dp^L>0Bi3AQH5tjU9T7^IBu|zcT|%Q9iJC;ko%ASAtRAmPt)ED;>$S`23NM(@MAMpxBF}$K z@)&Byh(9ljsix@8a~y?Sgku9Qgfk&oRwQ!>@6OagP$TPAe0TWfmiim!nY3|%KT)6N z2V|?@W%E2D^qBsc`p=((Cx#Rn(5gwQ2D1K&`6HeD{#KtLfK#^fdF_4eqO%Cj!M4WL zGWcEByUnP@ow7?7FhUn0RG|O|1Jx7J2|hbfa+vxvO)54s>gt;a)UvIOBkC@icTpHc z_*DpnNd{8%gPQq$7n)w)wBFJsost?JPB$UhdGN2#Q!(9_gsju8rCE@m%1 zFL+S}JkT&rTf%A>qnlc7q#9Hml4 zokP7&RjeRDw_7fx+O(p7=C958Livn9wTo1-N=off32|{|S-Z4b#=g&lwH_^-VhuK1 z-U570jUGeu`#&E#h;wBQW)5as|ESD%Hbt#yuQ;4JoN=9fT&Y><7Sa={75XF;CZr`K z=PpD{G?3hHwabI(j>fJJ46xLKU_B4 zG~8^!Bb))#Hr; zAVoVRK!asgde&^V`^UpLqg9?&rd8Fr-uSnPxQXI%>#W7B%@#_1Z#`7jg)ceH-cGib znGWsKKl`sU(`xZoD~Br=j%#@*RyMy?dNki@kru_3DaB79XY=XLElg;e=v(?OzioDF z#a(f%x2KRH+T&H=sr)vF>09Yv;2-2)^NN5HE>$AcAQdt&_GiC%R<@4F-}6>Sjvr(I za*X%NY04QA!WZTh?DlN&*cZ|fH1;TL5A7Itv32*^vpX2|T0i_Y8+T5y*D_r*cox$c z(fPZ3vU_!4jb`1v8-%IiIQ33MUN*i^h?LE=ftvW^SoGP0g#Atw`n%<_F4f@MTOx`sm$c33Lgzy+>PXnpv=5E z8ae8m5py#Wn9u3K@Em%IHDZtH41W$L?9(4S*?+zsdsN}}=N{wEw|um!89ycfqcbCZ zluWNz2Qv$c_-fog=X}p07er_uY4^R+yq>vv8`C5$Sfrs5`vXtemT)yn@prC9cUf)T z3QJU?Lk9Is)Xb2dqxVP;ZDaZ?wXf=59aXJMQ@xocgs`lzqF;)$j%6HqkS4~a!&YK2 z#(8XdCO!ATgdZo1^FsRa@M-Kao7?z4>-Sk+euwi(pHv^g8wjf>D?3Mku$WK4Ec^hH z8==S(-D$?kyXJSFM&iOm(fQea5xya8X7|+X`g*mfZgdpJ1^OBNb4syIk^SZP_GHBv zCEbeM(Qv=VVaIjb_0RPQ%Ztt_>mn-$Gq8!v&hnLczj8*)Nk_%Vzvox8*(}K@$#T|Y zbCNyjVrHFw&$(M^!L^>2>iotX@(E!bus5i+(A>Ols6#0{dz8}u(O>rsx$!_d8 zy5@Hcl77B};)>@z|J0^k%ZU@mD#S9vM($v;Ew{{0#Lmu>_*73jW?|H>(@SM(y@kPB z#XQ%4J-s`&+w!?jbh+oCw+tHK5Bv>DN614teyc}j0E`SMZ+c&mZ?w5eX>;iC+0j8v z4hjcwiNyIoX>(jcXMqT zHDxr)`NFv0_IH>28bOnfdG?|g{*X(gDRfN2b&dsN*G~6Cl~ysV=8o0{R69-t*n>6Mm=9ZGU`Hyl$3j*7WPX60V*1azC(deLeaZ z=ZpV@R=y5!XIqQV7Ul>B4 zXRy9ecm~|Qc;9PWmzBNFil&Ixy_(&W9@+n1>_qTEKro9BEp9_IsV~gT1axh{0od>X z-$=W}Vs&~Z@PZjPQ_v70xY|9Nc-wEq$xn9|ofljH_x)B#A29E)S-d3y;)Vv{s|E7h zhB;|H<(Gq!U{217MIX5DLwSK#ue>Ky*WM;W$SFBQu?=yU=D|_)k&JKNAijGiDR@8z zyNIEuc4@ZFbL$uLRT>^ucKOXsdh2z^8~V=+!X77UZuehZrIl=?15vTzs1u11qq*El zyHu&g5hDROm)He62XX&B4imw zf2|okS@9wlqIPmDPesrwX&prucz;R;Pd6DCi9ih>j_M%l{Kd+lGL;-9VR+he(B}@( zD*GsoTYuE|3Xxs&(e zZ;Sy&q51xMK``OHH@Q-6#R)71I=Pirua;fqe#hV-ylK%IdAE)zDzgI(S>=LI%xc!J zBExj&1Rx7Y#Xx*p(JEs{FDYyax(cDb%>3ckQ&W+@r2l=bS+j%h;986^U4+9Aw%Y+v zDw}L5Am@eQ_>0(@HXHts%S%BP6%>YZ=r}o zUH|REG_%Gu_hZ(NOhl?p*6!D8dE_H{@wU(R{ zD9=RQ*rFup;`-FW&tW(wzp-86-Zso33)2Gys24E2^OmHFsX*xyAa(!9b9?0wockU5 zZ4n=Qd1!7!gF;I{`cJxmvzY1|pvVe=t6C57)gaQ~K@In2>UKHko2O$Irn3zE;!Hk8xSu^3-P?QHOL=#zc0DWmA*_q{^ zE4di2eP479Y&v@r>Rfzy&KO=u!n_!g$xly|P_J(Hmo3wgbQ1ACb?nlhuNsdyGx}5j zn87#iLp1>OX({90?MUpObzJ zu>XM3_#rxdH*dz_;`LW0wCJ!U?)~7tTarLgo)4xy|IPcT z`ta=td_w(elT?~gDVPz{$OcVJq+Ga)P$7UF@+C-)bhz_dN7S=PwpW}i|R zdsZ*tlhPfr_qdSKxA3|+(iLvY70~7uz_vErRNl<%z2%wWdlY=5*q3;W339|Vgl^Uj7Lsib@EaOCWHqw3Q7$k zn9CNl05HJ7j@G}|V*5;mI|;t<*Jt_vTiH+opliiZTbr227K4ap;y9Mw#?>?)7s3KT zR1!o|d&i?oX4j2cz3TOa?^JBp78*YfhWW>F*yt&OPyn~hfc^Ji#(!S2CSE{~P@|WA zCdz6qL@?&Oj>x`^E^d(`1)?CHd-Rf)NPYRRLp&l`AZea);aHn2qrkvbs2Fu?I|yIT zXqEU+UN@&OdHKK(4d5mKkW7klC50e1S6`d>(TaG`aIoY*z~co*S-Bp8i~HOE7{N5o zC@n%sgQ^M`3Me`PpMCgRj{^G=6-#WK6TTVAWXS%d7id2O9q1s39paK)Q=W{G$qXhU zB8{lx0IR1C1>I>3_)EH(3S#s=v~J>m*Ba;44by+$ZR4tB3 z^6zz=`&p>trb_-^Lh7d54pRLts1uGe3WuxwPep=E@QP4}{#j!B^vnC0E=bWmk zykrJ4*db%@M`??}E5(=3LqCX(5W>O8#(cR2VcBS~?r2f8$k;+A;mEjS(u^Te{^cPg z+57L||GpFgJ`dbTf;Krt1%WV2$|;OK6Ay(;e7jU=yLA*;F#o-^MuDJwh!vvZh86T< zP>B(sG1WAEwTSS!7C2OS5yGbRQ(7m;0J;~g*8~cB@b^1VKU%MJjxhGx#rs_m6Y1M) z4q*bgopw!MQN+ki_NrmiS(lp$*ZV}(f>SU2ojc7&#L81P>oeQaD2!all;FNksg>tKLii&-j?i@lLUZv^DZ#$d-}oo3T`20ck;dgm~r#g)Tv0;m*`nUJ0ebTgpK{ zR74T+-T9$H9#IPb+uX#a&uS$SFFDTxwoT2$7~(wi%)B1DvoRkaN-YGLY7jUF;z zeRlwvR(sR=LqK^AsSN7?8YPN&2+i#b>w@#RjTq1o-{=DxdMVNK-x7{a3&`CO?xmo0S{J90eb{^F5XN~u6DPWFu7@cbvM zg8MW7VKVb%T%553V8^JqJpz!7AZu&Z_bH1K`$jv7Sit>7uCSCcdif)P!T=b4J0_BY zw&%MxpZ^xY>5M76#;Ei+F!u0TohE)3>*CR1G%~(rc?P4q@sCP%xO93<6$Zme3?Br4Fx*?XK~a#y zMA9X8x3acDp5}Y~8_cwQ!mIq1e?Gq_YvGR{+XE$4P zzT6I${&bk_nRe;>agm{N#>StstW!_yV9D|@rz-weDG=t*{>^z7!98%aG64GKc-X0Z z?k{MUfEuQQn`#Efy&Yx zVQY<2-0d<0V%GUak$;_NXWRI7;?6^=9BeYVrc@TMhiuKX<4B z7?q{qPw!i~zqhZR>rOTkJD6rU?ik zpn(4}YvLiM%uU8Rs48CLyx16H`KROKm7zo4M}8KT^pmptv^r)a>2|6u>>dPExFF0_ z*c_8YnZ5R~1-C+-G%!BU5KxeOcaA*a`{UNo&}JM6!i?9^Q~Z$1yZUz6KP&5TpFw}3 z4pfPtDjoOf6(|;9?_5TV|Xxm z=;|{~@nr`>aDN@->wywJNsmKm;$F>fGHjhp*A_r6L1y@=H4prFQi3JI_X$jcznoyc zk*`(49m`*-qMrb7=G>|cf+yQ{nuZ`DA)@u$Y|#Lar)GKL^YM`CG=&3z-&|&U%lKcJ zH*Q5~kzS?K&b})T>Ur2dFvq++i}m*Q>+eNKG^kD^$vJb$i%n6?Ykh4uDR8%)ovW5p z6&s(qfR{1(6-4x+zT&CtsYxPo> z*pfJ|9|0p}ZRVO{kB_IA23jPquNI<}VrgJoV!9YSm_4u*_m{YA*vcaoa{@Ql9ykd7 zt6OR}us|1!(y4ea96-d4v(S$Q8clatJ5ggD*Y6&yjQQQPs>ejx6JRCwSR{&A%}D9| zAeCZPdk$9sNKPk(M|BMT`un;waaBH;B25rqkbya1@Xlg?J5|ZpN7H zMUjePq({#&wMvV_&6)!)B7d@f@Z`nAK8QV~mL=ibFk13kN0Iu7VQ+ez|5C!`l6M%* zbprP1?DGWI5_F5_gxw3mw~c_j*wga#JZvlrzJTZLS@xnb?aj-+)OQTkuM7@x@Br#@ z94sjV2C_Lf;M*WjGE2?;9Y;c9VcUk^0s)bQ#UywsCZ>@-lPj7`zT8H)@Ii0zjCD75 zVZ@4so}rmN>h}V&4JIy5VaxlrQo^I;gqQ@1Xp!qrhEmKtGA4GFQxc?Ko6DMI_*aEV z-w`Z$UC<3(4SeWr==rtt6@*N~s5-#6E6AY<3E2H;9ru93&&OA(%!MZe->#fPL?e@98V^?Z&ur(0CfIr6f>%f9f-S&~jeCnLHki@{E}@OMrjxv}R1Zr5=Sa zNy5{4x3nNcXF=P0(bNzvPG{r6W3Z7Hp*q4l@U2!f5_W}dbfL)r!5Vm}uQV(K0Moz5 zQ$$@rVZvXib_+Z;=ac{Nuhn|qVtT$mYARbAWA09B(xA=hxETE23-Id>U}d+~b5~CI z?R&N5&e6Gj5h)C$21OD18Vo%2hn{-P4Wm?pXe1VgUv{lhRa}qv%LuzauN2@+ub8V5 z23MW4=1=YHG!!hnpUoP;e3U_#(yYH=@t_~N@-El~?c8nnA#OfS-lkQLNLwV*rwE%B zGn{#VNuj}nDI7i;>2OuFO6E(%2tM|R<7}%Ndb<*OpEAY5NVQm~I1bvN6kw9|2$>;) z-{{m{xBJSh4iTwjsjS)_7DeDx-1z#(Z;D}jPW&#yvf;J1dy@uBrJX)0`5^eLcu$C( z&yKRQ0`$T_8+vTLT3KOD>a5_0oGP*6f&|hXo#p${aha_>Pzy=s!&M z>T3?8N&dM1x2J^~V*pc3PGcjT;V@i|9*+w*+(sx%jkZsJUW{9giNHvoef44CbP(+J zEB_BoU=DB>vRTQMxZXt2H=4}o5skST6^>4c7f#Ja5LN`LyGqD?BLp$O5;$))AnyfI zYhHY4*EZYG=fylB_s=q?=+lyVVktLGstJMW6K_8}*upJTvMm>XssF`O?Wq_OvwJ-9 zaWC8YE=7AnVZiRb&9eZ4gwH90YQTFk&TH^kM9!Nw-To7P`ikGRb@v4PhfIK{0N(Nl zocI``W0aw=fzwKc2ltVciGZZtmi(zrYxZ5c1kA17?Kt`e`hNWdryoDSRT(ZGPG9*0 zGPAVEv407op6rhK!%Ss3m+1G^vr-Y`n+C_ri7!NEkflq#0#YNF3v=1Ri*_})%L|=$ zsomWav;OV)pZ1ORt3O;D!-0K>b~12k#>g@2TJxJfGlr*?aEUd!fBmXAea`DSs$Qrb zpp*q|qS}QC1oR#;eht?BhHFx-rjKXF=qpy0YTVtUo|n_E%v@F6J5>Hb$qiT#*mjfL z&(&fq+&CuPhJffC=^@um`O6GT+D_YjWW(&Dd_j(C5k_+Oj4*uXq0{-Ud5XeVRIDK) z$iT0Pl*~LR1v=1azn65xVtLVD=@$+%Czk^p8+#cD$S0!NS^gc6l$6H%Mud71%014j-z5d$zMf1WI^rDJIH9B2!aFd1=WAd_%6G zkLKoW-!@<#v-ZYRIG|TpvqqA#E5X(6%Xer;%zA(b1{!a*O}PD!csdunApuxi^LUk? zk!V&p{YG*6QAsgokEQG(y-w-OUI8vBm>y3$7=s<7QF&`fme+=WRlV&9Oxli6P1d_v zgFZ+G`EvXm<@}Zlw_2O$kdP_!fpHLCv)*P|x*)gqsn^33*ls3?#l-h5SK7d@A^dY9 z9uAL1aFJ31yDp1U(g;C|X$lDm(hX0#lUCCwn3$_|g#+9Ze7k=5t;R#(I-$c}vTNKr zQXf_1>6$=Vf;$;h}3&GE}dN=4Or65Mm@(3^+1Ts^TQXwi)EI^pts@ zAT<=gWN}X;-e{sU3rp69GpNx(7g%stZflwYv8dVgD{!W>a^D8{rJ=DpOIIY}lF>iX zg0#2(@av3RY#7m?uvFD_n0CIAHIc64yADx|7_QH&nW%-Y3YZ%(*=Z`I!|6d!N&WsO z`U^Ia%`hlIAvQ0*H%Xsa0k#MdUQGc|oM`x$b0du~fZx~gW>7WJ-{J}_rl<1m=;rqH zPNAV*((~9ZUlx%>>hEbv=kVFA1B`z_82@&&-W!9}zlT?bp~X#{r-NJlxXn*QTMg;8{4-MI zsnVa=hn_BmvEG{x`-YstRo~Y*z+y7jf3ext%DT2;{dz3rv^vb_Ufs@YyGzHJO^q5t z8Q<}_usL-1XcheBGR_L)1kFg1Ly_EH?xaW#qI>VltB)w`9`F~S5)GHLgc&3D6i#oe zKD9_8iXe70*&crqS0K>>W2g2A@EW{&9)N!URji*0h`$7& zJ+|wIjRQ+Ryg>b(a>f7V$Rbu_6HS+v`ayqE{lLQxi(e;93aaIM$7;YS1d+As=Y{Em z@V66XU?avKu>amuqvXwY0CbXsL*JT$iNG~14ipyHSJF?u+X=IFlpw`@>KOLRLYQ~5 zyUbsiFD-~{#);o7CcxOy6W)91}y5MFSJbX(07th8$ z)-i-29o*UnUK!-QVsqLG-;rg-Bm1Ns3%<0$l8B#vH$CN@RzT^$p{S`R(T8JY_vxgQ zhYS;A#jnb=GE52a(9qV&1K{W2od>y?E+|u$TP!@QeMoVy4ikYD+w#|S{8a{6&BJE3 zNE5&BX-q5STb7zQ7-2wLJGrT0$MuD89vi}Hamz60ou?NdpZUT}r}L(TQk5zl8l$5< zeS`v+a3CGtSNocFU4Ja#SMOJ5o6nMFwKZZHA%Y2bwVNgp5A=D#48$FhTe!s{+R51y z?&6%PteNY=G@o3O^+pxn$8k-d^tacx!aa}5vZ4}kZ);y=O#g&-mvd+)4&~Gpl)bdG zHjUsFJB!ji*(I#2#b&hp6Dhuinj>1BvgUJTa`dMsb3|2j4Jj*(uJUqE-qUJhkyxiZ zf(6o5R#}hxjpYJLOJ`(Xx<*6LBIou%@y)Vbq*O%2n`k;xd=B;YZ0^_C5rtSm_ov0S z8nHhHeyTz`v?3)^Fb8K#zQqTgjfLEZwPvu1fubj#_iC+0?+~@@9wwl;a4d*=yew%> z`Lo8gf0Wj!Y2E{4{kyNhT}?vdzk^)_A@8cP1J8zH#G&kLyZxk~k=ro+-Hn5cQRGs` z0vs4%>hCVqitB7ULP;}~OZMPW;|e`FaMT(yj+48mi9ZKfU#;3p;@5ryez29MWJMgh zw`UM*b0{|{lu&#NtHY0ER`t;!`EFxc->1Z=9I-zz>8>hLINpZNA@C35awmwldQR-V zEwvK3DVfX!QAYu$uNYhw;N#oPt6U#@jmZkGIOG5EGLh`K@o$ zPLwaq6+k&!e#ISMg&^gLp5^(4AN9s)T9p$CQx^|{GSWv{x+BO)$RoC?;T3vm2xHIb zTPxrR39y?iXkZPq(?@iXZ+=M}>eMxjw_2~jA9c4&B5H3w)4+S+^hs`Aq`4BWbT+wD znrJAczIDiHkA97)+=T_nN<$$!5Bif7j0u~9x|7p!CL}nQI5vw#pCNZyIM*ku^xp;j zOUQe>ZK^iufUph^IZ#@ha7L+Fn{lHiIm-CyBJ=%6DJsW#FZN0n;O%^p5gH?!v(2&$ zU<8n;<#&9ca<_rTmIwe&Vdd-5F0OMcK4jhNx%cytiU$_vA@{kQ(KuhN-H)}K>7pgv zc5MQklFL@^+)9DsbewF$sD7}V_HjeTlLuWj_<10f_q{EtOz?JR-642qK-784n->}L zhOlfd(Ku|vBR)9Cp8g^EM$RKGzv2d(qQIXFp}KUZ+m`OydmX@+QYyuD+1x0`+qQ2d zmq((8ZiP zA_c}zny-F`{&mUkKCIL_W+OXQ=W&S(Mkx zZWM49U;TA#30P-6nb3A2{((3%R}AKP*Ccdk4e$TpKe}BwCF-*iF%rff(Njf0OAW`e z$ebKFQy^4zM^P^(A}_tQ21<*03#+kKaHK6_e>ndNcN`Y9C&0RE&u)0$p#^5(RtADm z3hQd#s;=833h@`u-Wf56b*ZO_K3sz9DDNee*$9YN8Rqr-IV%1OUa!BZ&6PcD8De%p zRO-C8BmX)C#5bDLj1oilaVY!4kHwv%j<7Ic((%`x-W55jdOTC+oFoce67o0*0}_<)GKwq zy$<>c=YZija|Hr)pc{VO@K=TGT_IhAJ9)2wF^PZ~WS}pI*5|nU?wT7va8v0CC8a_x zeKMDDwdB&QPkxmyq-tbtaDkB==rG;+=jvB;=U(`;H4CwhR~!@z!ygxW{I>1$qud%#C^PYM2nII zMUprp{-V}43!&68W=8dyiRml#BCs&Qp!!|ngY6aJ_DBg(fM7e1Jj>?=?5(OtJmYua zYg=K`tTKiSJLi|bAN1)&Ns@;K80Gfr!b&E<$7FRL%3bUqL69xu+V||nqRrtDxU0Qt zQXYaH7j0ns{oF<{N=aB@{e@T>d#1O3!HH+K`^(p<1n%Mxy?2b6`RdW@!l|z}O@-uA z6srYaYj(HvhtRbPCnQM-d5)`ilJM`^ZlRgl#dADw!qIEA-1 z^2@o_@<3dNiwX@)5M3znG=Y+=oWP!vLSmLj(P^=l%Z?;2r#tq?gffECXbNN=bmRF6 z$3xODu#*f6${x3aAolMHDcE^P`a9K!DsFahZcR9r!oBFTMG+eGi%(u57_ybQJc{}_ z%C+3w%XP|5?Rddz$u(#c6{b$YjtCYh=Ov!1q(|U8w3ROS*Zgk&^B0OP2`E}=eRZv+ zyu)7mpz4PX4SzvN#rykrvlLXi)@r&N} zi057TB4=lnf9+NdlUIFl@14OCdFUTn;^W;qbcrL7`T8C4)IM;7Bv{B-O!1!HOM)L? z`;Ec#=XwMEU%XK+*Ld3q;{2o4hpTqI++y6h5bt59tqfB{GMUv4o?&=OI9jFEQ?EkxcA})`ZPPMS#uaRJ9;Qq5`B3JBe_D za07Y`E6{~nnK;V3I~a;3?^h3Q>k5J1rcodsy@&69z>Aq56*H_$k@M!PqAbi!(J4mN z=^QO08}H$S0(@harQ%UvEH~(VPGDKr>zwFybA>A1|V4s^NC^ingm$PqA|%RWBz zBl}!(j9ENytZfJd7Y;W@_BFs*pol>Mx?#g@O7z@cS#dm2@B&Ohi)!w7JEXF{U1HGE z&&4UoUaDDPaD_J*kC(ypf`_6Zo5;X-K?ShMC^GQ}GVuUOYAnWiPM*MC-#?UsZqf(S zAV5|a=pu*gTW3HBHczh(cZ`u5ra1{tBsz@iwnXdRAe^NFW_2id$*-TD4GhE%@mjC9 zePt}6O=~+>-7{T`7`rMZgMFK-;+(~SwUvBwo=FEg-P!r``KPPxT2wI#RXvSm2Y1j1 z;}2G0A(>MMi+&s`T<`Re7G|!WMmw~(gal9^>DjOP{XSoh1Dnn`5q)vuL)-u2l;1e} zfq-(%b2awtveY6XT_Nr9?}8XI;xaCqF=LuB-o+X1DPw{n;i%G4F!xEdY28C$?NQ0I+l^t$FDf4|#YyRt@A(H;#q5jJZbJ^NS43HK!d;te!RK;pUi+Kul zM2h8(1(+z$+x-w$`qMUp9KC##5GFuL*on!3Cy{r-3XjeDxD(q<;<~*1iNdHw2koyW<{4U=-5=NzB+x7Z!i~Zo8&tuV>=fcA zBm4&k?1R~G0FB8q>wg0+7zx8%;`o?<&_WYf+R=+s?~wj)@c+qG<{u7_Q!+4q6ZH$< zf1p5Td>9EG>+l_F7|alr2!^h5LS)UR`!{HdhLNb^9&o|=hb4@K$&epDed0fap@9sH z#C+yf8;l$!yey0-Qn)dzsDFe1x2^yC+WN83HmVp?3d|sAhWvtt2Z^W9KQ<>{Ts=1D zO%!JzcYiF`A9FDBi`6lFXTEtVB!>w5de_VAb9#p83M1C5Wjm~<$_e83`67i%CO9)) z1_GvET!C8qdcml8_`FGDLtYsdIl|&A&5SqD@qCs zX|R55YBx$1nq&F_ZqP7}fd3bU$Mdj|5?D7i>0#on{XeH$%2m}fpf!G#q;P7!ty zg#|UAEbq2L4UrtP-ZK2EBr2s`malwx_2QN z86#CU{OD3R?K>cvVyObTXDip6M}$2CfBn+-f3QT-8*Fd9^%dR}=)+#h9t?djx<194 z?o;K3^fiXzT@WXZ&1{z@Ead!O@0w}Sjp5^XP<_n~j6<=v?^eZbziQE@bfkuFjQoWK znFsv2)E9moO6R^V71e7$#coBHC}ELE(9dM*$Losjy>RYlg_!G0!_TezGF%OcQGRXB z3d}@%wLX3XkpLF-%c_yXRc5hxrHtL0S1{(&Ye%T4o+WQN}k~)@4fn* zcEWPLq)f+E?cX4M_cKPbeGK%FXj|O*FQ84{>}u8%tt#j1QRmCI{I3kN+3OIAarn+q zIY8s}Ywkjgrfd^Ok{7@B=sto0inqsFKoKjh=catjc5~w4}PE}3Yv5r-TQHa zJQ}8_zpWtS*1Iq`)2Y=kzNt-j)2j0c-xzS*J#Yv<38RN%>80@{z3Dib({U0f#6;ru zG89uFs9k6C`q=q}pk{Svn^TZJ0>@^#>Gv4r05yDeTP?9sEy%{kqkaf_VDkce{2DHx z!XxMY!XQaE)w>0uSa0~f>Kx5fnX(uucWXzJuqGs7^z7XzQosv1X#u7$K8gtVqEeFI zR7QR5o~D}NF>EF1Kou@V*@g~Y#}7fh$SlBR_c?#A7G-JrpeQX&=~o@2PDW<93xcX1 zzpKw0RnDn3BD~W7Rcc?3oAG}>i(3K^y%kn)`ut%63<}P|VUaTEDHS@YuhD3vZZ871 zvo33$SpxijY%*l9)^frcXnmap=Cjm-&Au>HO&FEvW6}^ap-uHqEn-Re(wQntu)ir? z#PO!$kVl5x#uuhupmm%kr-0pu(kOder|^H+h(Npk(Z7*N$?cltZgL(o!!x#d|07v}X`Pe69wRp7xyWJuJfbS3eR2{cA}4t2A(6T)3a2P(i|* zk@!r+YMbA5-Zc(f-$qMu$>-iOWnnI|?zY+}x!&CW4YzGsubxQzY31bU1%v_Ex-xM( z<^G_WJ!<>vwZU-i)ya-1Dt=PbDvw9__*{T3x>qyGc;c4A%YEZIVyZ<&P$$H#cdu>PYQwvDzntFd5rf_6eGAd~K80!CxB|kF${K zoWUn-@gHP8A*Q62hjk>X>@l|zJcPGc^UFT4N+-WFKP->bj1#2h*!<<3k2E1T)b6b` zbZp}eGP|I{z8^(hjEx@O-1zXx2<%+^@>#}&@8Sn)>|i&xT=tiF<4RxQO+lwXlV&H& z)l2%$3WZDA>^f6k$nlE8>sxK#O&LFi0Ukf=#7FLWrKHxydI6eSESM9t#S|6jeko+} z{C$O9!zEIp68O-RtKz9S#?--e?4&9cI35x+9|$W#UAd| z5}s(?u+eL>lCcicO}4f#Y2Om++f~*2n}2oOF^1dA8L=c}y|lu`o%*ZT;*a%h!5ScS z45XMOtX6G%RJyfOVnj3Sblrx7dcy7B^o~nT?V_&;k`-T6@jEzU%;VjTQsSYE3aAHv zqbTmHO2pnY&n~diM6G(5gWI+6^*W4pO9NZ}#8ua0B8dQfN3av%w|g?|q)mREhn$7Q zhy zTRA?U%_p09KMIdjf_)&d=*$F-!xtG#c`f~_)N!f!cY{GAoDNbFQ@zH%KmD}$ktN{Z zm{GIzQJcbvMl)Y`Nt9-rVOR#VYm^RR(mgcdD=49kj`tl~O6oP)<{l@eF|h?fAu?tD zZVV^LWM12fT#U=KdS>utM3P{@VZtnu#Sp`ZKt5NBV0t7g`Wu(J+Q92q?~G{p{0JxF zi=^K5IwwF?i#p;^FUs~)RQ(!ZGba|>7XmXzhzHfZs1y^9r(Mk_gBH(CQ{B2N;O_&8 zp!c5Xq;_6@PZ8lWH9H*;%2%tIt736PpG#B1NHA_-FpC5Bmf}|MmJ-5|U1UN$LQq-{ z5)l|!_ZKBQT!rQJhQr8^O88!@&G|8t1mTweVfovEi36-ecE_wNL*etQ2Y0nb<=k5I z{cc_RFR*_-wg;h+J9U_D?i2vqs)3n0ma&?%xbswPfimpo!>K!<-%3YTa*csYG)7(x zqw!9!8qlU4StL{Z?fM+|acDIo>|fU_ zRin^j`$>WFO$pYH7jUmkG6F&T`_}=DitBz>-1yBbD>&SQd7es~trtW7>IEZR zdqub)$pX@5v|Bs;API`!87oN{Ph;%=al z-r-HSp2 zC4`tt+AntGz4Iv>`I-(()TJ1til15;87Wm6Z;gT6diymSdurmW%WeEe^@Dr?4hsQ} zb`%L#{puK&%|f5?i1#HMut|vo-D5MHyJ`aA@OGV0=R+OkQF`CqV(H08z49z>zGxhP z)dGXojAEAFeA10NsA*yDSYfJ;*Xv!dC;_4wO59%_LR7sGZ zP{%06jt(=Zql@3^i@IAt{td0_?iM|L472qmwRz^U{+`JeRLlWDtA4+mh05p z7BfauHC7()4lRB^j)F0sPJTd0`;GNYrx$3Z3f85)7FX1aT?Z{Q!ThuHy z!j{6PrpF+a)@_FA1iP`ve}%H{?_qyN#u%*Gm0E4zXQHyZfQ~#$Oe2)N{>|IP&^tA` zfcjBiE67;2qq{UWv{641YZ7UqULzC{W+!3jgZoVme2 zBbefkcaaS7@UR&Lo?!hks>PF`Jy^VZ-vqcOu|RwKwMe3d=-OA_WeLNg`7$cR ztWf)5@|7?~B#|tj=ypoO{R45!3(W?7qT%7J7yv53rWQ|8x`h3nxUh6td-Kidixk3K z#>ZGUSA!E$j!H)50i~El^O8~Od_jj0)bamQ%9%exwf=GZ%$Q*eX~s4~WXl>^vPQ-- zmLwrNHxm*VjOD-u}BSa}%wu&Z_+_EInFyCkHzwrI}eCG3E7$#Ak#N(wU70O zor}zRnZ(n#@jandC9%lSH93eeFxl=+Y8QIdD=3hhH%(c+aK5IBL1J#UdhrvSGX|wM;}?%c`lu#Uv?gyvV?rbzPo%<)&QXpz zWY=t(Uf)_4I~*PSc$L8a(L#Q>y+DoFXMIfMNVM)hsOD+UnQMg}3wb>!esKwE7Y`9~ zY8jq84gXxI&RRlW@DL%_1~#U_ZnSKl#awN5~WKUSc|#s=N>RzunfD~&syxN zl&9_>e4eTrb%^n5RnMwai7RL%y~=6qz82s1rSV>K(NZ=&qpl=hz# z)^fFE2E8|TZV9ArN~%08$bR{5Wc6F+gB-y`v14mrPAKtn?Qga1@U4?q1AcE%YsMdQ z8qJ=MmJuP)@3m^ZO?EMpQ$nLr?uezdcvpm^%H>v3?YCDwejn;RXWhBGG!2%bZ>3Yx z#nEf4{3ciCS9a~L$J?Ctl3?c1t>L0Me*IJhB2BwI=Oni}pZv+eYKl`0Lr#343An{V ze~M{)4Y{l?W#|hzc$^APuZ~=I6L=qf4;PdZbldkMk%w&e->%G@`?j+_b4%I8 zttrugFK0Y-p`s3$Mb;4eOs3Dkm6MLV?$C&_nlw8Da2_Bau#r{P*3DpwUT7i+vk~!5m>1ayZ=2%Z&JnQXZqYQ(gz&)wIqi z^Sy{FzF6qdgPv8H*^=ab!AimxQ1N=5URGBd@m5nw1W{H(F)$n_xNEr8>pr8-ZT8yc zH-@=t$2Cl#Y1V<`iNk&LRhso1(b`HIn@;zS_k04SDAvW_4t0Vv5%<44Sv|}blW;`% z1LPAZNy$$JvxT%JbY5ub-`k`Uly9pLNox*4d$`?*gW1=vCgX+V1yd=&e-x!BE1x## z^YG{65;e}?0gy~z`=qPjDQeE34Q;)@u&?;By!ZvJCO0hPYXRe}MZ@rvee1X1}@YP(vNA z&h?i2-tDnhrs& zt8bK^M3*Wm794s?-Nv#v_vc(EZUcHXThr7c!0;GuT4!L?u$8ANlvPiKQsWt^ zW5n1h->n_9YD#)nOeEIbtu{mh%J39x|Ji49c%S3R%P+k>jdv@G7AOwkcSesI&+2lS z_7^`_EU#g2bdJjR{Vqkx>d4&E5cU1rCigWk9Pa%o|AkslNYXNSs_H$sytA1X@Of|K z4TEgXJvwJr;(Us)v4T>Q)@@bkly@d2ekMbEkL;D0W)qQdL3n0R^1hTPnKH}w`(5+a z0f=Rz$3Ci{tbJt9y$w3VSr~sBf@6V67?F4UqRgNS#2+@F5Q)yGHwd}R9!%zR!H6kCmM49V({0y8I5BC*!MK+C86-PSrR;WXxT^Gr28p76y#Z;in#>pnF#h{b= z=~js9qum7w2!=LASeNSwLSeE`Hs+;%_B;xGl4eJZGhvkxqtCWKJ>MMOlp zvH0tiRXTfSH{s2?nYQm=*@hb_u*D|gIYJNJ2$qNHx#W1?kcD6dok5F|X#;U^G&f~H zx*D>i%{O-tr7{54*d}u`ognjhy>{gbe#8NWPYI@}V^=4^s(o@?q7wWx=4`(hZo}+P z-lqXH_K0qlhc?hah~QN361aN4C-lBYlkab%$=$Y1LI&ATW4wZ^$bj-A#cP z=zYHqeQL-zgcjcP2=jy(z%I-1kIplE--1@Xn9>L27CXH5gD}&*rja}j8F1eO4gLfuiMxji zXrmqP^mKy$D%)0S-&^xDLB^A8ND|y|Ak)K$5-X<)BgY1Q-8l6+_j2zn-uC zk}iUV+0oqq*;dmroqIsH!ypII+$(KCT%gCVdN9T;#(rE~fCAf;MUXnC;7;)6GE^Zr(cRW6>9Mhuc3*KQa+FwWP?AzslvY3>DRM0EyV!0 z$;s_0bC#IEbMw`o%P)A8rdctO`*7+99A!GHBmoMXHQXQ|*pDyD+G3=m`2g12sq^Yv zN=E1xu5JLu7zoe_;jp|f&Qp>(% ze&VS<^~p#quyz_{K0BC^&Qajz4+rFK;0k%a zc%dK=dx=31&q~%gU_vg}6^t|?*Fe>khk!g6GIGVxF)`%X=|2;wZgDmrF(e7yJJy#e zpY-Wd-4r!B{o`ReZ5yz}^1tJo^6f~(9s7dJNAYKoE= z1eH8&vAJPZ6726b-4izwW&0OP4WT7T0ZKKLI@D};yjA$gcU~c5L;h{qqh-MEWQGWF z>G(>%5G4I6TWJmafgqhRjQM>O6XL9{nhK~ExpZ=IcRVupqbonILTa!z*%FY9V^1zSUYlP zC140zhJdbh{HdH<*-^U~9nA(9@I4hNH%;^VYU2J@hFQBopJdxvu0vf1y-^6Jt)9_s z2zht%b_X%HoiZenV)>mvF9NO73FJ$RKQhaiN>PT66UE@cAzNKhT6Cs)a$gbH7J^^% zV3g-NEdoqu15Wq`MgwkcrdMuu|K7MEohc+hksrIsP~|5k?@kW6fg72B_u97d6prFt znor1}497y;NSnDX9;xt?iX%m*%9}gbaZUfC9pJEJz>0jSpM$LCKGrhp8sw{P4+|o|{xT9>t zEQKSHWqUL?Xv+7&7`R9wNDe@?y@dJ?9h!*D)49* zfm01RiyO(;m{DyHT@*x=q3-j2#4{rm;wjIy>=P2ew@c}u)oi5)GTJtgx1n~z9)^Ef zS^{y!I|1n!4T`RQ7}1Z#!`vZnrw-omv(E|NL@<;X@t4|Z^n;US>cZHo2Y}l7&if{v zGZkv`dQEkP*qzN~zqt<7q)W%9c!2;c2*6#6_f$ZEH0(27!5T<)1sEP(#;+crr(*=3 zj#7xbf0-mgqepu74#L7Nv##9oyNl!wDEw0_^Bre1O_iMm#t%nYFds!+2}4}P5MlOe z4!gjUas(vERCg7*OhROshFdk*Dlrs(A?CTTl%D5a6))DXLuQu18h)ACdnHq=7&)ZtV^!mgq}M1M@a_ynFvY zF&E1URGnW<|1XCY$PqLG{gGt_5?RKW|9dbXo)qLpXZ|ipW^MBcoiec^)*F#x{|Bs5 Bt3?0+ literal 0 HcmV?d00001 diff --git a/test/statsCases/modules-assets/node_modules/a/index.js b/test/statsCases/modules-assets/node_modules/a/index.js new file mode 100644 index 000000000..d89ed76f0 --- /dev/null +++ b/test/statsCases/modules-assets/node_modules/a/index.js @@ -0,0 +1 @@ +import './1.png' diff --git a/test/statsCases/modules-assets/webpack.config.js b/test/statsCases/modules-assets/webpack.config.js new file mode 100644 index 000000000..737008e5a --- /dev/null +++ b/test/statsCases/modules-assets/webpack.config.js @@ -0,0 +1,17 @@ +module.exports = { + mode: "production", + entry: "./index", + stats: { + chunks: true, + chunkModules: true, + modules: true + }, + module: { + rules: [ + { + test: /\.png$/, + use: ["file-loader"] + } + ] + } +}; From 92a3fc2cd36c4cdc864865f1bfc37dc1d0fbe447 Mon Sep 17 00:00:00 2001 From: marcalexiei Date: Fri, 2 Mar 2018 17:05:23 +0100 Subject: [PATCH 083/162] =?UTF-8?q?Config=20error=20message=20=E2=80=93=20?= =?UTF-8?q?fix=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/WebpackOptionsValidationError.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index 851bbb5a6..4d8abd7d5 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -155,7 +155,7 @@ class WebpackOptionsValidationError extends WebpackError { case "debug": return ( `${baseMessage}\n` + - "The 'debug' property was removed in webpack 2.\n" + + "The 'debug' property was removed in webpack 2.0.0.\n" + "Loaders should be updated to allow passing this option via loader options in module.rules.\n" + "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" + "plugins: [\n" + @@ -166,8 +166,7 @@ class WebpackOptionsValidationError extends WebpackError { ); } return ( - baseMessage + - "\n" + + `${baseMessage}\n` + "For typos: please correct them.\n" + "For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.\n" + " Loaders should be updated to allow passing options via loader options in module.rules.\n" + From b0e14df9ce2af4efafe98be44c2235ffa1ba9d7e Mon Sep 17 00:00:00 2001 From: zacanger Date: Fri, 2 Mar 2018 09:50:13 -0700 Subject: [PATCH 084/162] Set optimization.splitChunks to false in test webpack config. --- test/configCases/split-chunks/no-options/webpack.config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/configCases/split-chunks/no-options/webpack.config.js b/test/configCases/split-chunks/no-options/webpack.config.js index 16fb53733..eb349acba 100644 --- a/test/configCases/split-chunks/no-options/webpack.config.js +++ b/test/configCases/split-chunks/no-options/webpack.config.js @@ -9,5 +9,8 @@ module.exports = { output: { filename: "[name].js" }, + optimization: { + splitChunks: false + }, plugins: [new SplitChunksPlugin()] }; From 2c8ea603680fb731f86db385360ff6e01a8d1b51 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sat, 3 Mar 2018 15:41:30 +0100 Subject: [PATCH 085/162] expose stuff and all non-bundle modules --- lib/JavascriptModulesPlugin.js | 4 ++-- lib/webpack.js | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/JavascriptModulesPlugin.js b/lib/JavascriptModulesPlugin.js index 6394f465f..09489117c 100644 --- a/lib/JavascriptModulesPlugin.js +++ b/lib/JavascriptModulesPlugin.js @@ -85,7 +85,7 @@ class JavascriptModulesPlugin { (source, chunk, hash, moduleTemplate, dependencyTemplates) => { return Template.renderChunkModules( chunk, - () => true, + m => typeof m.source === "function", moduleTemplate, dependencyTemplates, "/******/ " @@ -128,7 +128,7 @@ class JavascriptModulesPlugin { renderJavascript(chunkTemplate, chunk, moduleTemplate, dependencyTemplates) { const moduleSources = Template.renderChunkModules( chunk, - m => true, + m => typeof m.source === "function", moduleTemplate, dependencyTemplates ); diff --git a/lib/webpack.js b/lib/webpack.js index ed9fa612a..73bcbc6bd 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -89,6 +89,7 @@ exportPlugins(exports, { ContextExclusionPlugin: () => require("./ContextExclusionPlugin"), ContextReplacementPlugin: () => require("./ContextReplacementPlugin"), DefinePlugin: () => require("./DefinePlugin"), + Dependency: () => require("./Dependency"), DllPlugin: () => require("./DllPlugin"), DllReferencePlugin: () => require("./DllReferencePlugin"), EnvironmentPlugin: () => require("./EnvironmentPlugin"), @@ -103,6 +104,7 @@ exportPlugins(exports, { LoaderOptionsPlugin: () => require("./LoaderOptionsPlugin"), LoaderTargetPlugin: () => require("./LoaderTargetPlugin"), MemoryOutputFileSystem: () => require("./MemoryOutputFileSystem"), + Module: () => require("./Module"), ModuleFilenameHelpers: () => require("./ModuleFilenameHelpers"), NamedChunksPlugin: () => require("./NamedChunksPlugin"), NamedModulesPlugin: () => require("./NamedModulesPlugin"), @@ -116,6 +118,7 @@ exportPlugins(exports, { SingleEntryPlugin: () => require("./SingleEntryPlugin"), SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"), Stats: () => require("./Stats"), + Template: () => require("./Template"), UmdMainTemplatePlugin: () => require("./UmdMainTemplatePlugin"), WatchIgnorePlugin: () => require("./WatchIgnorePlugin") }); From 81235e133121f1896a1b469d10f40e8381539d90 Mon Sep 17 00:00:00 2001 From: Clark Du Date: Sun, 4 Mar 2018 13:24:10 +0800 Subject: [PATCH 086/162] Add stats.moduleAssets to show assets inside modules in the Stats --- lib/Stats.js | 11 ++++++++++- schemas/WebpackOptions.json | 4 ++++ test/statsCases/module-assets/expected.txt | 12 ++++++++++++ .../{modules-assets => module-assets}/index.js | 0 .../node_modules/a/1.png | Bin .../node_modules/a/index.js | 0 .../webpack.config.js | 13 +++++++++++-- test/statsCases/modules-assets/expected.txt | 16 ---------------- 8 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 test/statsCases/module-assets/expected.txt rename test/statsCases/{modules-assets => module-assets}/index.js (100%) rename test/statsCases/{modules-assets => module-assets}/node_modules/a/1.png (100%) rename test/statsCases/{modules-assets => module-assets}/node_modules/a/index.js (100%) rename test/statsCases/{modules-assets => module-assets}/webpack.config.js (50%) delete mode 100644 test/statsCases/modules-assets/expected.txt diff --git a/lib/Stats.js b/lib/Stats.js index 5ec4c4b31..ae14729ee 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -136,6 +136,10 @@ class Stats { options.nestedModules, true ); + const showModuleAssets = optionOrLocalFallback( + options.moduleAssets, + !forToString + ); const showDepth = optionOrLocalFallback(options.depth, !forToString); const showCachedModules = optionOrLocalFallback(options.cached, true); const showCachedAssets = optionOrLocalFallback(options.cachedAssets, true); @@ -417,7 +421,6 @@ class Stats { optional: module.optional, prefetched: module.prefetched, chunks: Array.from(module.chunksIterable, chunk => chunk.id), - assets: Object.keys(module.buildInfo.assets || {}), issuer: module.issuer && module.issuer.identifier(), issuerId: module.issuer && module.issuer.id, issuerName: @@ -435,6 +438,9 @@ class Stats { errors: module.errors ? module.errors.length : 0, warnings: module.warnings ? module.warnings.length : 0 }; + if (showModuleAssets) { + obj.assets = Object.keys(module.buildInfo.assets || {}); + } if (showReasons) { obj.reasons = module.reasons .map(reason => { @@ -867,6 +873,9 @@ class Stats { if (module.built) { colors.green(" [built]"); } + if (module.assets && module.assets.length) { + colors.magenta(` [${module.assets.length} asset]`); + } if (module.prefetched) { colors.magenta(" [prefetched]"); } diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index 62b8ee077..50e62510c 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -1757,6 +1757,10 @@ "type": "boolean", "description": "add information about modules nested in other modules (like with module concatenation)" }, + "moduleAssets": { + "type": "boolean", + "description": "add information about assets inside modules" + }, "children": { "type": "boolean", "description": "add children information" diff --git a/test/statsCases/module-assets/expected.txt b/test/statsCases/module-assets/expected.txt new file mode 100644 index 000000000..bd2e4fb34 --- /dev/null +++ b/test/statsCases/module-assets/expected.txt @@ -0,0 +1,12 @@ +Hash: d71bd16b0b20f34e994a +Time: Xms +Built at: Thu Jan 01 1970 00:00:00 GMT +Entrypoint main = main.js +chunk {0} 0.js 68 bytes <{1}> [rendered] + [0] ./node_modules/a/1.png 51 bytes {0} [built] [1 asset] + [1] ./node_modules/a/index.js 17 bytes {0} [built] +chunk {1} main.js (main) 12 bytes >{0}< [entry] [rendered] + [2] ./index.js 12 bytes {1} [built] + [0] ./node_modules/a/1.png 51 bytes {0} [built] [1 asset] + [1] ./node_modules/a/index.js 17 bytes {0} [built] + [2] ./index.js 12 bytes {1} [built] \ No newline at end of file diff --git a/test/statsCases/modules-assets/index.js b/test/statsCases/module-assets/index.js similarity index 100% rename from test/statsCases/modules-assets/index.js rename to test/statsCases/module-assets/index.js diff --git a/test/statsCases/modules-assets/node_modules/a/1.png b/test/statsCases/module-assets/node_modules/a/1.png similarity index 100% rename from test/statsCases/modules-assets/node_modules/a/1.png rename to test/statsCases/module-assets/node_modules/a/1.png diff --git a/test/statsCases/modules-assets/node_modules/a/index.js b/test/statsCases/module-assets/node_modules/a/index.js similarity index 100% rename from test/statsCases/modules-assets/node_modules/a/index.js rename to test/statsCases/module-assets/node_modules/a/index.js diff --git a/test/statsCases/modules-assets/webpack.config.js b/test/statsCases/module-assets/webpack.config.js similarity index 50% rename from test/statsCases/modules-assets/webpack.config.js rename to test/statsCases/module-assets/webpack.config.js index 737008e5a..2b4661614 100644 --- a/test/statsCases/modules-assets/webpack.config.js +++ b/test/statsCases/module-assets/webpack.config.js @@ -2,15 +2,24 @@ module.exports = { mode: "production", entry: "./index", stats: { + assets: false, chunks: true, chunkModules: true, - modules: true + modules: true, + moduleAssets: true }, module: { rules: [ { test: /\.png$/, - use: ["file-loader"] + use: [ + { + loader: "file-loader", + options: { + name: "[name].[ext]" + } + } + ] } ] } diff --git a/test/statsCases/modules-assets/expected.txt b/test/statsCases/modules-assets/expected.txt deleted file mode 100644 index 3599c10a1..000000000 --- a/test/statsCases/modules-assets/expected.txt +++ /dev/null @@ -1,16 +0,0 @@ -Hash: e6165e79d5ae833a8859 -Time: Xms -Built at: Thu Jan 01 1970 00:00:00 GMT - Asset Size Chunks Chunk Names -155613d841c408f2a34b9c81cdfd3e8c.png 37.7 KiB [emitted] - 0.js 607 bytes 0 [emitted] - main.js 6.76 KiB 1 [emitted] main -Entrypoint main = main.js -chunk {0} 0.js 99 bytes <{1}> [rendered] - [0] ./node_modules/a/1.png 82 bytes {0} [built] - [1] ./node_modules/a/index.js 17 bytes {0} [built] -chunk {1} main.js (main) 12 bytes >{0}< [entry] [rendered] - [2] ./index.js 12 bytes {1} [built] - [0] ./node_modules/a/1.png 82 bytes {0} [built] - [1] ./node_modules/a/index.js 17 bytes {0} [built] - [2] ./index.js 12 bytes {1} [built] \ No newline at end of file From e12f414a15c13d88b3e4b269c34558ad4a8f1a72 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sun, 4 Mar 2018 10:12:51 +0100 Subject: [PATCH 087/162] larger timeouts to make CI more stable --- test/Examples.test.js | 2 +- test/HotTestCases.test.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Examples.test.js b/test/Examples.test.js index f57016c5d..d298cf8c1 100644 --- a/test/Examples.test.js +++ b/test/Examples.test.js @@ -19,7 +19,7 @@ describe("Examples", () => { it("should compile " + path.relative(basePath, examplePath), function( done ) { - this.timeout(20000); + this.timeout(30000); let options = {}; let webpackConfigPath = path.join(examplePath, "webpack.config.js"); webpackConfigPath = diff --git a/test/HotTestCases.test.js b/test/HotTestCases.test.js index 1f42a9605..1a4cd4c8b 100644 --- a/test/HotTestCases.test.js +++ b/test/HotTestCases.test.js @@ -29,6 +29,7 @@ describe("HotTestCases", () => { this.timeout(10000); }); it(testName + " should compile", done => { + this.timeout(10000); const testDirectory = path.join(casesPath, category.name, testName); const outputDirectory = path.join( __dirname, From f916fc0bb70585cf04a92cd99e004e4879f1d337 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sun, 4 Mar 2018 11:39:44 +0100 Subject: [PATCH 088/162] 4.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 384dd095e..17450f4ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "4.0.1", + "version": "4.1.0", "author": "Tobias Koppers @sokra", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "license": "MIT", From bb2320cf13c4444f22714ed328e6655e4c97f5a0 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 5 Mar 2018 08:38:32 +0100 Subject: [PATCH 089/162] Update Stats.js --- lib/Stats.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Stats.js b/lib/Stats.js index d7a4cb405..938dc89ec 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -730,7 +730,13 @@ class Stats { if (typeof obj.builtAt === "number") { const builtAtDate = new Date(obj.builtAt); colors.normal("Built at: "); - colors.normal(builtAtDate.toLocaleDateString()); + colors.normal( + builtAtDate.toLocaleDateString({ + day: "2-digit", + month: "2-digit", + year: "numeric" + }) + ); colors.normal(" "); colors.bold(builtAtDate.toLocaleTimeString()); newline(); From 1248616af0ad6cdfc7c5b1113e092ec5b3b484f6 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 5 Mar 2018 09:31:37 +0100 Subject: [PATCH 090/162] convert arrow function to normal function --- test/HotTestCases.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/HotTestCases.test.js b/test/HotTestCases.test.js index 1a4cd4c8b..e9d4254e9 100644 --- a/test/HotTestCases.test.js +++ b/test/HotTestCases.test.js @@ -28,7 +28,7 @@ describe("HotTestCases", () => { const suite = describe(testName, function() { this.timeout(10000); }); - it(testName + " should compile", done => { + it(testName + " should compile", function(done) { this.timeout(10000); const testDirectory = path.join(casesPath, category.name, testName); const outputDirectory = path.join( From 23208a311ca2fce52a36db7d4fe38cda2eac0747 Mon Sep 17 00:00:00 2001 From: Clark Du Date: Mon, 5 Mar 2018 17:12:40 +0800 Subject: [PATCH 091/162] Show plural if assets are more than one --- lib/Stats.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Stats.js b/lib/Stats.js index ae14729ee..3cf246dba 100644 --- a/lib/Stats.js +++ b/lib/Stats.js @@ -874,7 +874,11 @@ class Stats { colors.green(" [built]"); } if (module.assets && module.assets.length) { - colors.magenta(` [${module.assets.length} asset]`); + colors.magenta( + ` [${module.assets.length} asset${ + module.assets.length === 1 ? "" : "s" + }]` + ); } if (module.prefetched) { colors.magenta(" [prefetched]"); From 1b37115e4bad95cfdeefd49cfd1062e56ddd69f5 Mon Sep 17 00:00:00 2001 From: chuckd Date: Mon, 5 Mar 2018 07:51:12 -0500 Subject: [PATCH 092/162] Make AMD parser modules extensible --- .../AMDDefineDependencyParserPlugin.js | 493 +++++++++--------- ...AMDRequireDependenciesBlockParserPlugin.js | 345 ++++++------ 2 files changed, 430 insertions(+), 408 deletions(-) diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js index c6959acd3..3ecf54b67 100644 --- a/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -40,272 +40,275 @@ class AMDDefineDependencyParserPlugin { this.options = options; } - newDefineDependency( - range, - arrayRange, - functionRange, - objectRange, - namedModule - ) { - return new AMDDefineDependency( - range, - arrayRange, - functionRange, - objectRange, - namedModule + apply(parser) { + this.parser = parser; + parser.hooks.call.for("define").tap( + "AMDDefineDependencyParserPlugin", + this.processCallDefine.bind( + Object.create(this, { + parser: { value: parser } + }) + ) ); } - apply(parser) { - const options = this.options; - - const processArray = (expr, param, identifiers, namedModule) => { - if (param.isArray()) { - param.items.forEach((param, idx) => { - if ( - param.isString() && - ["require", "module", "exports"].includes(param.string) - ) - identifiers[idx] = param.string; - const result = processItem(expr, param, namedModule); - if (result === undefined) { - processContext(expr, param); - } - }); - return true; - } else if (param.isConstArray()) { - const deps = []; - param.array.forEach((request, idx) => { - let dep; - let localModule; - if (request === "require") { - identifiers[idx] = request; - dep = "__webpack_require__"; - } else if (["exports", "module"].includes(request)) { - identifiers[idx] = request; - dep = request; - } else if ( - (localModule = LocalModulesHelpers.getLocalModule( - parser.state, - request - )) - ) { - // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } else { - dep = new AMDRequireItemDependency(request); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - } - deps.push(dep); - }); - const dep = new AMDRequireArrayDependency(deps, param.range); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }; - const processItem = (expr, param, namedModule) => { - if (param.isConditional()) { - param.options.forEach(param => { - const result = processItem(expr, param); - if (result === undefined) { - processContext(expr, param); - } - }); - return true; - } else if (param.isString()) { - let dep, localModule; - if (param.string === "require") { - dep = new ConstDependency("__webpack_require__", param.range); - } else if (["require", "exports", "module"].includes(param.string)) { - dep = new ConstDependency(param.string, param.range); + processArray(expr, param, identifiers, namedModule) { + const parser = this.parser; + if (param.isArray()) { + param.items.forEach((param, idx) => { + if ( + param.isString() && + ["require", "module", "exports"].includes(param.string) + ) + identifiers[idx] = param.string; + const result = this.processItem(expr, param, namedModule); + if (result === undefined) { + this.processContext(expr, param); + } + }); + return true; + } else if (param.isConstArray()) { + const deps = []; + param.array.forEach((request, idx) => { + let dep; + let localModule; + if (request === "require") { + identifiers[idx] = request; + dep = "__webpack_require__"; + } else if (["exports", "module"].includes(request)) { + identifiers[idx] = request; + dep = request; } else if ( (localModule = LocalModulesHelpers.getLocalModule( parser.state, - param.string, - namedModule + request )) ) { // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule, param.range); + dep = new LocalModuleDependency(localModule); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); } else { - dep = new AMDRequireItemDependency(param.string, param.range); + dep = this.newRequireItemDependency(request); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); } - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }; - const processContext = (expr, param) => { - const dep = ContextDependencyHelpers.create( - AMDRequireContextDependency, - param.range, - param, - expr, - options - ); - if (!dep) return; + deps.push(dep); + }); + const dep = this.newRequireArrayDependency(deps, param.range); dep.loc = expr.loc; dep.optional = !!parser.scope.inTry; parser.state.current.addDependency(dep); return true; - }; - - parser.hooks.call - .for("define") - .tap("AMDDefineDependencyParserPlugin", expr => { - let array, fn, obj, namedModule; - switch (expr.arguments.length) { - case 1: - if (isCallable(expr.arguments[0])) { - // define(f() {...}) - fn = expr.arguments[0]; - } else if (expr.arguments[0].type === "ObjectExpression") { - // define({...}) - obj = expr.arguments[0]; - } else { - // define(expr) - // unclear if function or object - obj = fn = expr.arguments[0]; - } - break; - case 2: - if (expr.arguments[0].type === "Literal") { - namedModule = expr.arguments[0].value; - // define("...", ...) - if (isCallable(expr.arguments[1])) { - // define("...", f() {...}) - fn = expr.arguments[1]; - } else if (expr.arguments[1].type === "ObjectExpression") { - // define("...", {...}) - obj = expr.arguments[1]; - } else { - // define("...", expr) - // unclear if function or object - obj = fn = expr.arguments[1]; - } - } else { - array = expr.arguments[0]; - if (isCallable(expr.arguments[1])) { - // define([...], f() {}) - fn = expr.arguments[1]; - } else if (expr.arguments[1].type === "ObjectExpression") { - // define([...], {...}) - obj = expr.arguments[1]; - } else { - // define([...], expr) - // unclear if function or object - obj = fn = expr.arguments[1]; - } - } - break; - case 3: - // define("...", [...], f() {...}) - namedModule = expr.arguments[0].value; - array = expr.arguments[1]; - if (isCallable(expr.arguments[2])) { - // define("...", [...], f() {}) - fn = expr.arguments[2]; - } else if (expr.arguments[2].type === "ObjectExpression") { - // define("...", [...], {...}) - obj = expr.arguments[2]; - } else { - // define("...", [...], expr) - // unclear if function or object - obj = fn = expr.arguments[2]; - } - break; - default: - return; + } + } + processItem(expr, param, namedModule) { + const parser = this.parser; + if (param.isConditional()) { + param.options.forEach(param => { + const result = this.processItem(expr, param); + if (result === undefined) { + this.processContext(expr, param); } - let fnParams = null; - let fnParamsOffset = 0; - if (fn) { - if (isUnboundFunctionExpression(fn)) fnParams = fn.params; - else if (isBoundFunctionExpression(fn)) { - fnParams = fn.callee.object.params; - fnParamsOffset = fn.arguments.length - 1; - if (fnParamsOffset < 0) fnParamsOffset = 0; + }); + return true; + } else if (param.isString()) { + let dep, localModule; + if (param.string === "require") { + dep = new ConstDependency("__webpack_require__", param.range); + } else if (["require", "exports", "module"].includes(param.string)) { + dep = new ConstDependency(param.string, param.range); + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string, + namedModule + )) + ) { + // eslint-disable-line no-cond-assign + dep = new LocalModuleDependency(localModule, param.range); + } else { + dep = this.newRequireItemDependency(param.string, param.range); + } + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processContext(expr, param) { + const dep = ContextDependencyHelpers.create( + AMDRequireContextDependency, + param.range, + param, + expr, + this.options + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!this.parser.scope.inTry; + this.parser.state.current.addDependency(dep); + return true; + } + + processCallDefine(expr) { + const parser = this.parser; + let array, fn, obj, namedModule; + switch (expr.arguments.length) { + case 1: + if (isCallable(expr.arguments[0])) { + // define(f() {...}) + fn = expr.arguments[0]; + } else if (expr.arguments[0].type === "ObjectExpression") { + // define({...}) + obj = expr.arguments[0]; + } else { + // define(expr) + // unclear if function or object + obj = fn = expr.arguments[0]; + } + break; + case 2: + if (expr.arguments[0].type === "Literal") { + namedModule = expr.arguments[0].value; + // define("...", ...) + if (isCallable(expr.arguments[1])) { + // define("...", f() {...}) + fn = expr.arguments[1]; + } else if (expr.arguments[1].type === "ObjectExpression") { + // define("...", {...}) + obj = expr.arguments[1]; + } else { + // define("...", expr) + // unclear if function or object + obj = fn = expr.arguments[1]; + } + } else { + array = expr.arguments[0]; + if (isCallable(expr.arguments[1])) { + // define([...], f() {}) + fn = expr.arguments[1]; + } else if (expr.arguments[1].type === "ObjectExpression") { + // define([...], {...}) + obj = expr.arguments[1]; + } else { + // define([...], expr) + // unclear if function or object + obj = fn = expr.arguments[1]; } } - let fnRenames = parser.scope.renames.createChild(); - let identifiers; - if (array) { - identifiers = {}; - const param = parser.evaluateExpression(array); - const result = processArray(expr, param, identifiers, namedModule); - if (!result) return; - if (fnParams) - fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { - if (identifiers[idx]) { - fnRenames.set(param.name, identifiers[idx]); - return false; - } - return true; - }); + break; + case 3: + // define("...", [...], f() {...}) + namedModule = expr.arguments[0].value; + array = expr.arguments[1]; + if (isCallable(expr.arguments[2])) { + // define("...", [...], f() {}) + fn = expr.arguments[2]; + } else if (expr.arguments[2].type === "ObjectExpression") { + // define("...", [...], {...}) + obj = expr.arguments[2]; } else { - identifiers = ["require", "exports", "module"]; - if (fnParams) - fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { - if (identifiers[idx]) { - fnRenames.set(param.name, identifiers[idx]); - return false; - } - return true; - }); + // define("...", [...], expr) + // unclear if function or object + obj = fn = expr.arguments[2]; } - let inTry; - if (fn && isUnboundFunctionExpression(fn)) { - inTry = parser.scope.inTry; - parser.inScope(fnParams, () => { - parser.scope.renames = fnRenames; - parser.scope.inTry = inTry; - if (fn.body.type === "BlockStatement") - parser.walkStatement(fn.body); - else parser.walkExpression(fn.body); - }); - } else if (fn && isBoundFunctionExpression(fn)) { - inTry = parser.scope.inTry; - parser.inScope( - fn.callee.object.params.filter( - i => !["require", "module", "exports"].includes(i.name) - ), - () => { - parser.scope.renames = fnRenames; - parser.scope.inTry = inTry; - if (fn.callee.object.body.type === "BlockStatement") - parser.walkStatement(fn.callee.object.body); - else parser.walkExpression(fn.callee.object.body); - } - ); - if (fn.arguments) parser.walkExpressions(fn.arguments); - } else if (fn || obj) { - parser.walkExpression(fn || obj); - } - - const dep = this.newDefineDependency( - expr.range, - array ? array.range : null, - fn ? fn.range : null, - obj ? obj.range : null, - namedModule ? namedModule : null - ); - dep.loc = expr.loc; - if (namedModule) { - dep.localModule = LocalModulesHelpers.addLocalModule( - parser.state, - namedModule - ); - } - parser.state.current.addDependency(dep); - return true; + break; + default: + return; + } + let fnParams = null; + let fnParamsOffset = 0; + if (fn) { + if (isUnboundFunctionExpression(fn)) fnParams = fn.params; + else if (isBoundFunctionExpression(fn)) { + fnParams = fn.callee.object.params; + fnParamsOffset = fn.arguments.length - 1; + if (fnParamsOffset < 0) fnParamsOffset = 0; + } + } + let fnRenames = parser.scope.renames.createChild(); + let identifiers; + if (array) { + identifiers = {}; + const param = parser.evaluateExpression(array); + const result = this.processArray(expr, param, identifiers, namedModule); + if (!result) return; + if (fnParams) + fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { + if (identifiers[idx]) { + fnRenames.set(param.name, identifiers[idx]); + return false; + } + return true; + }); + } else { + identifiers = ["require", "exports", "module"]; + if (fnParams) + fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { + if (identifiers[idx]) { + fnRenames.set(param.name, identifiers[idx]); + return false; + } + return true; + }); + } + let inTry; + if (fn && isUnboundFunctionExpression(fn)) { + inTry = parser.scope.inTry; + parser.inScope(fnParams, () => { + parser.scope.renames = fnRenames; + parser.scope.inTry = inTry; + if (fn.body.type === "BlockStatement") + parser.walkStatement(fn.body); + else parser.walkExpression(fn.body); }); + } else if (fn && isBoundFunctionExpression(fn)) { + inTry = parser.scope.inTry; + parser.inScope( + fn.callee.object.params.filter( + i => !["require", "module", "exports"].includes(i.name) + ), + () => { + parser.scope.renames = fnRenames; + parser.scope.inTry = inTry; + if (fn.callee.object.body.type === "BlockStatement") + parser.walkStatement(fn.callee.object.body); + else parser.walkExpression(fn.callee.object.body); + } + ); + if (fn.arguments) parser.walkExpressions(fn.arguments); + } else if (fn || obj) { + parser.walkExpression(fn || obj); + } + + const dep = this.newDefineDependency( + expr.range, + array ? array.range : null, + fn ? fn.range : null, + obj ? obj.range : null, + namedModule ? namedModule : null + ); + dep.loc = expr.loc; + if (namedModule) { + dep.localModule = LocalModulesHelpers.addLocalModule( + parser.state, + namedModule + ); + } + parser.state.current.addDependency(dep); + return true; + } + + newDefineDependency(...args) { + return new AMDDefineDependency(...args); + } + newRequireArrayDependency(...args) { + return new AMDRequireArrayDependency(...args); + } + newRequireItemDependency(...args) { + return new AMDRequireItemDependency(...args); } } module.exports = AMDDefineDependencyParserPlugin; diff --git a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js index 673c86fac..f8afac505 100644 --- a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +++ b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js @@ -46,8 +46,117 @@ class AMDRequireDependenciesBlockParserPlugin { } apply(parser) { - const options = this.options; + this.parser = parser; + parser.hooks.call.for("require").tap( + "AMDRequireDependenciesBlockParserPlugin", + this.processCallRequire.bind( + Object.create(this, { + parser: { value: parser } + }) + ) + ); + } + processArray(expr, param) { + const parser = this.parser; + if (param.isArray()) { + for (const p of param.items) { + const result = this.processItem(expr, p); + if (result === undefined) { + this.processContext(expr, p); + } + } + return true; + } else if (param.isConstArray()) { + const deps = []; + for (const request of param.array) { + let dep, localModule; + if (request === "require") { + dep = "__webpack_require__"; + } else if (["exports", "module"].includes(request)) { + dep = request; + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + request + )) + ) { + // eslint-disable-line no-cond-assign + dep = new LocalModuleDependency(localModule); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + } else { + dep = this.newRequireItemDependency(request); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + } + deps.push(dep); + } + const dep = this.newRequireArrayDependency(deps, param.range); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processItem(expr, param) { + const parser = this.parser; + if (param.isConditional()) { + for (const p of param.options) { + const result = this.processItem(expr, p); + if (result === undefined) { + this.processContext(expr, p); + } + } + return true; + } else if (param.isString()) { + let dep, localModule; + if (param.string === "require") { + dep = new ConstDependency("__webpack_require__", param.string); + } else if (param.string === "module") { + dep = new ConstDependency( + parser.state.module.buildInfo.moduleArgument, + param.range + ); + } else if (param.string === "exports") { + dep = new ConstDependency( + parser.state.module.buildInfo.exportsArgument, + param.range + ); + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string + )) + ) { + // eslint-disable-line no-cond-assign + dep = new LocalModuleDependency(localModule, param.range); + } else { + dep = this.newRequireItemDependency(param.string, param.range); + } + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processContext(expr, param) { + const dep = ContextDependencyHelpers.create( + AMDRequireContextDependency, + param.range, + param, + expr, + this.options + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!this.parser.scope.inTry; + this.parser.state.current.addDependency(dep); + return true; + } + + processCallRequire(expr) { const processArrayForRequestString = param => { if (param.isArray()) { const result = param.items.map(item => @@ -70,172 +179,82 @@ class AMDRequireDependenciesBlockParserPlugin { } }; - const processArray = (expr, param) => { - if (param.isArray()) { - for (const p of param.items) { - const result = processItem(expr, p); - if (result === undefined) { - processContext(expr, p); - } - } - return true; - } else if (param.isConstArray()) { - const deps = []; - for (const request of param.array) { - let dep, localModule; - if (request === "require") { - dep = "__webpack_require__"; - } else if (["exports", "module"].includes(request)) { - dep = request; - } else if ( - (localModule = LocalModulesHelpers.getLocalModule( - parser.state, - request - )) - ) { - // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } else { - dep = new AMDRequireItemDependency(request); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - } - deps.push(dep); - } - const dep = new AMDRequireArrayDependency(deps, param.range); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }; - const processItem = (expr, param) => { - if (param.isConditional()) { - for (const p of param.options) { - const result = processItem(expr, p); - if (result === undefined) { - processContext(expr, p); - } - } - return true; - } else if (param.isString()) { - let dep, localModule; - if (param.string === "require") { - dep = new ConstDependency("__webpack_require__", param.string); - } else if (param.string === "module") { - dep = new ConstDependency( - parser.state.module.buildInfo.moduleArgument, - param.range - ); - } else if (param.string === "exports") { - dep = new ConstDependency( - parser.state.module.buildInfo.exportsArgument, - param.range - ); - } else if ( - (localModule = LocalModulesHelpers.getLocalModule( - parser.state, - param.string - )) - ) { - // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule, param.range); - } else { - dep = new AMDRequireItemDependency(param.string, param.range); - } - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }; - const processContext = (expr, param) => { - const dep = ContextDependencyHelpers.create( - AMDRequireContextDependency, - param.range, - param, + let param; + let dep; + let result; + + const parser = this.parser; + const old = parser.state.current; + + if (expr.arguments.length >= 1) { + param = parser.evaluateExpression(expr.arguments[0]); + dep = this.newRequireDependenciesBlock( expr, - options + param.range, + expr.arguments.length > 1 ? expr.arguments[1].range : null, + expr.arguments.length > 2 ? expr.arguments[2].range : null, + parser.state.module, + expr.loc, + processArrayForRequestString(param) ); - if (!dep) return; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - }; + parser.state.current = dep; + } - parser.hooks.call - .for("require") - .tap("AMDRequireDependenciesBlockParserPlugin", expr => { - let param; - let dep; - let result; - - const old = parser.state.current; - - if (expr.arguments.length >= 1) { - param = parser.evaluateExpression(expr.arguments[0]); - dep = new AMDRequireDependenciesBlock( - expr, - param.range, - expr.arguments.length > 1 ? expr.arguments[1].range : null, - expr.arguments.length > 2 ? expr.arguments[2].range : null, - parser.state.module, - expr.loc, - processArrayForRequestString(param) - ); - parser.state.current = dep; - } - - if (expr.arguments.length === 1) { - parser.inScope([], () => { - result = processArray(expr, param); - }); - parser.state.current = old; - if (!result) return; - parser.state.current.addBlock(dep); - return true; - } - - if (expr.arguments.length === 2 || expr.arguments.length === 3) { - try { - parser.inScope([], () => { - result = processArray(expr, param); - }); - if (!result) { - dep = new UnsupportedDependency("unsupported", expr.range); - old.addDependency(dep); - if (parser.state.module) - parser.state.module.errors.push( - new UnsupportedFeatureWarning( - parser.state.module, - "Cannot statically analyse 'require(..., ...)' in line " + - expr.loc.start.line - ) - ); - dep = null; - return true; - } - dep.functionBindThis = this.processFunctionArgument( - parser, - expr.arguments[1] - ); - if (expr.arguments.length === 3) { - dep.errorCallbackBindThis = this.processFunctionArgument( - parser, - expr.arguments[2] - ); - } - } finally { - parser.state.current = old; - if (dep) parser.state.current.addBlock(dep); - } - return true; - } + if (expr.arguments.length === 1) { + parser.inScope([], () => { + result = this.processArray(expr, param); }); + parser.state.current = old; + if (!result) return; + parser.state.current.addBlock(dep); + return true; + } + + if (expr.arguments.length === 2 || expr.arguments.length === 3) { + try { + parser.inScope([], () => { + result = this.processArray(expr, param); + }); + if (!result) { + dep = new UnsupportedDependency("unsupported", expr.range); + old.addDependency(dep); + if (parser.state.module) + parser.state.module.errors.push( + new UnsupportedFeatureWarning( + parser.state.module, + "Cannot statically analyse 'require(..., ...)' in line " + + expr.loc.start.line + ) + ); + dep = null; + return true; + } + dep.functionBindThis = this.processFunctionArgument( + parser, + expr.arguments[1] + ); + if (expr.arguments.length === 3) { + dep.errorCallbackBindThis = this.processFunctionArgument( + parser, + expr.arguments[2] + ); + } + } finally { + parser.state.current = old; + if (dep) parser.state.current.addBlock(dep); + } + return true; + } + } + + newRequireDependenciesBlock(...args) { + return new AMDRequireDependenciesBlock(...args); + } + newRequireItemDependency(...args) { + return new AMDRequireItemDependency(...args); + } + newRequireArrayDependency(...args) { + return new AMDRequireArrayDependency(...args); } } module.exports = AMDRequireDependenciesBlockParserPlugin; From 2428b14ab3cf49423f09b241f681f08129649952 Mon Sep 17 00:00:00 2001 From: chuckd Date: Mon, 5 Mar 2018 10:22:38 -0500 Subject: [PATCH 093/162] Fix linter error --- lib/dependencies/AMDDefineDependencyParserPlugin.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js index 3ecf54b67..477dbc64b 100644 --- a/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -260,9 +260,11 @@ class AMDDefineDependencyParserPlugin { parser.inScope(fnParams, () => { parser.scope.renames = fnRenames; parser.scope.inTry = inTry; - if (fn.body.type === "BlockStatement") + if (fn.body.type === "BlockStatement") { parser.walkStatement(fn.body); - else parser.walkExpression(fn.body); + } else { + parser.walkExpression(fn.body); + } }); } else if (fn && isBoundFunctionExpression(fn)) { inTry = parser.scope.inTry; From c86cc80c0c72c511eb50045a2c456061294d8fca Mon Sep 17 00:00:00 2001 From: chuckd Date: Mon, 5 Mar 2018 11:10:46 -0500 Subject: [PATCH 094/162] Remove erronious this.parser assignments in apply methods --- lib/dependencies/AMDDefineDependencyParserPlugin.js | 1 - lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js index 477dbc64b..78e67dd75 100644 --- a/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -41,7 +41,6 @@ class AMDDefineDependencyParserPlugin { } apply(parser) { - this.parser = parser; parser.hooks.call.for("define").tap( "AMDDefineDependencyParserPlugin", this.processCallDefine.bind( diff --git a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js index f8afac505..5e2079921 100644 --- a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +++ b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js @@ -46,7 +46,6 @@ class AMDRequireDependenciesBlockParserPlugin { } apply(parser) { - this.parser = parser; parser.hooks.call.for("require").tap( "AMDRequireDependenciesBlockParserPlugin", this.processCallRequire.bind( From 57c6c4323c0655a19fea1d2dc350d7fba5ffe7a5 Mon Sep 17 00:00:00 2001 From: Jason Milloff Date: Mon, 5 Mar 2018 11:45:20 -0500 Subject: [PATCH 095/162] Add requested changes from PR comments --- lib/WebpackOptionsDefaulter.js | 2 +- .../source-map/array-as-output-library/index.js | 1 + .../source-map/array-as-output-library/webpack.config.js | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 test/configCases/source-map/array-as-output-library/index.js create mode 100644 test/configCases/source-map/array-as-output-library/webpack.config.js diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index e1a82ad86..015b1b792 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -129,7 +129,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { }); this.set("output.devtoolNamespace", "make", options => { if (Array.isArray(options.output.library)) - return [].concat(options.output.library).join("."); + return options.output.library.join("."); return options.output.library || ""; }); this.set("output.libraryTarget", "var"); diff --git a/test/configCases/source-map/array-as-output-library/index.js b/test/configCases/source-map/array-as-output-library/index.js new file mode 100644 index 000000000..8533042d2 --- /dev/null +++ b/test/configCases/source-map/array-as-output-library/index.js @@ -0,0 +1 @@ +it("should compile successfully when output.library is an array of strings", function() {}); diff --git a/test/configCases/source-map/array-as-output-library/webpack.config.js b/test/configCases/source-map/array-as-output-library/webpack.config.js new file mode 100644 index 000000000..0beba149e --- /dev/null +++ b/test/configCases/source-map/array-as-output-library/webpack.config.js @@ -0,0 +1,7 @@ +module.exports = { + devtool: "source-map", + output: { + filename: "MyLibrary.[name].js", + library: ["Foo", "[name]"] + } +}; From 1181c0effc59b2a23d435876e025ea8d7932afd4 Mon Sep 17 00:00:00 2001 From: Jason Milloff Date: Mon, 5 Mar 2018 12:13:21 -0500 Subject: [PATCH 096/162] Remove accidental filename setting which wasn't needed and was breaking test --- .../source-map/array-as-output-library/webpack.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/configCases/source-map/array-as-output-library/webpack.config.js b/test/configCases/source-map/array-as-output-library/webpack.config.js index 0beba149e..ee3cbe39b 100644 --- a/test/configCases/source-map/array-as-output-library/webpack.config.js +++ b/test/configCases/source-map/array-as-output-library/webpack.config.js @@ -1,7 +1,6 @@ module.exports = { devtool: "source-map", output: { - filename: "MyLibrary.[name].js", library: ["Foo", "[name]"] } }; From 883088e52136666bc639845f39209b528b4964ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bazyli=20Brzo=CC=81ska?= Date: Mon, 5 Mar 2018 22:46:45 +0100 Subject: [PATCH 097/162] fix(ProfilingPlugin): complete after the writeStream had finished flushing the data to the filesystem Fixes a race-condition where `events.json` might not yet be available immediately after compilation. --- lib/debug/ProfilingPlugin.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/debug/ProfilingPlugin.js b/lib/debug/ProfilingPlugin.js index 76fb36f95..2c05c368b 100644 --- a/lib/debug/ProfilingPlugin.js +++ b/lib/debug/ProfilingPlugin.js @@ -73,17 +73,18 @@ class Profiler { /** * @param {string} outputPath The location where to write the log. - * @returns {{trace: ?, counter: number, profiler: Profiler}} The trace object + * @returns {{trace: ?, counter: number, profiler: Profiler, fsStream: WriteStream}} The trace object */ function createTrace(outputPath) { const trace = new Trace({ noStream: true }); const profiler = new Profiler(inspector); + const fsStream = fs.createWriteStream(outputPath); let counter = 0; - trace.pipe(fs.createWriteStream(outputPath)); + trace.pipe(fsStream); // These are critical events that need to be inserted so that tools like // chrome dev tools can load the profile. trace.instantEvent({ @@ -119,7 +120,8 @@ function createTrace(outputPath) { return { trace, counter, - profiler + profiler, + fsStream }; } @@ -169,16 +171,17 @@ class ProfilingPlugin { ); // We need to write out the CPU profile when we are all done. - compiler.hooks.done.tap( + compiler.hooks.done.tapAsync( { name: pluginName, stage: Infinity }, - () => { + (stats, callback) => { tracer.profiler.stopProfiling().then(parsedResults => { if (parsedResults === undefined) { tracer.profiler.destroy(); tracer.trace.flush(); + tracer.fsStream.end(callback); return; } @@ -226,6 +229,7 @@ class ProfilingPlugin { tracer.profiler.destroy(); tracer.trace.flush(); + tracer.fsStream.end(callback); }); } ); From f9e7a17666471dab9e51889d090d6b9e449d554c Mon Sep 17 00:00:00 2001 From: Florent Cailhol Date: Tue, 6 Mar 2018 09:24:07 +0100 Subject: [PATCH 098/162] Escape module names --- lib/node/NodeMainTemplatePlugin.js | 4 +++- test/configCases/async-commons-chunk/node/index.js | 7 +++++++ .../configCases/async-commons-chunk/node/modules/a.js | 3 +++ .../configCases/async-commons-chunk/node/modules/b.js | 1 + .../configCases/async-commons-chunk/node/modules/c.js | 3 +++ .../async-commons-chunk/node/webpack.config.js | 11 +++++++++++ 6 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/configCases/async-commons-chunk/node/index.js create mode 100644 test/configCases/async-commons-chunk/node/modules/a.js create mode 100644 test/configCases/async-commons-chunk/node/modules/b.js create mode 100644 test/configCases/async-commons-chunk/node/modules/c.js create mode 100644 test/configCases/async-commons-chunk/node/webpack.config.js diff --git a/lib/node/NodeMainTemplatePlugin.js b/lib/node/NodeMainTemplatePlugin.js index 4182ab0ad..139a8a404 100644 --- a/lib/node/NodeMainTemplatePlugin.js +++ b/lib/node/NodeMainTemplatePlugin.js @@ -29,7 +29,9 @@ module.exports = class NodeMainTemplatePlugin { "// object to store loaded chunks", '// "0" means "already loaded"', "var installedChunks = {", - Template.indent(chunk.ids.map(id => `${id}: 0`).join(",\n")), + Template.indent( + chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n") + ), "};" ]); } diff --git a/test/configCases/async-commons-chunk/node/index.js b/test/configCases/async-commons-chunk/node/index.js new file mode 100644 index 000000000..87d0dbb34 --- /dev/null +++ b/test/configCases/async-commons-chunk/node/index.js @@ -0,0 +1,7 @@ +import "./modules/a"; + +it("should load", done => { + Promise.all([import("./modules/b"), import("./modules/c")]).then(() => { + done(); + }); +}); diff --git a/test/configCases/async-commons-chunk/node/modules/a.js b/test/configCases/async-commons-chunk/node/modules/a.js new file mode 100644 index 000000000..a6525eec9 --- /dev/null +++ b/test/configCases/async-commons-chunk/node/modules/a.js @@ -0,0 +1,3 @@ +import "./b"; + +export default "a"; diff --git a/test/configCases/async-commons-chunk/node/modules/b.js b/test/configCases/async-commons-chunk/node/modules/b.js new file mode 100644 index 000000000..eff703ff4 --- /dev/null +++ b/test/configCases/async-commons-chunk/node/modules/b.js @@ -0,0 +1 @@ +export default "b"; diff --git a/test/configCases/async-commons-chunk/node/modules/c.js b/test/configCases/async-commons-chunk/node/modules/c.js new file mode 100644 index 000000000..a7501e849 --- /dev/null +++ b/test/configCases/async-commons-chunk/node/modules/c.js @@ -0,0 +1,3 @@ +import("./a"); + +export default "c"; diff --git a/test/configCases/async-commons-chunk/node/webpack.config.js b/test/configCases/async-commons-chunk/node/webpack.config.js new file mode 100644 index 000000000..656d3a998 --- /dev/null +++ b/test/configCases/async-commons-chunk/node/webpack.config.js @@ -0,0 +1,11 @@ +module.exports = { + mode: "none", + entry: { + "foo/bar": "./" + }, + target: "node", + optimization: { + namedChunks: true, + namedModules: true + } +}; From 9eb4daa29731a098ef60b6fe9a4e8bd0e7f1f1e9 Mon Sep 17 00:00:00 2001 From: Florent Cailhol Date: Tue, 6 Mar 2018 11:40:47 +0100 Subject: [PATCH 099/162] Remove CCP link --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d2b0b62a9..79cda6f2d 100644 --- a/README.md +++ b/README.md @@ -81,14 +81,12 @@ within webpack itself use this plugin interface. This makes webpack very |Name|Status|Description| |:--:|:----:|:----------| -|[common-chunks-webpack-plugin][common]|![common-npm]|Generates chunks of common modules shared between entry points and splits them into separate bundles (e.g vendor.bundle.js && app.bundle.js)| |[extract-text-webpack-plugin][extract]|![extract-npm]|Extracts Text (CSS) from your bundles into a separate file (app.bundle.css)| |[compression-webpack-plugin][compression]|![compression-npm]|Prepares compressed versions of assets to serve them with Content-Encoding| |[i18n-webpack-plugin][i18n]|![i18n-npm]|Adds i18n support to your bundles| |[html-webpack-plugin][html-plugin]|![html-plugin-npm]| Simplifies creation of HTML files (`index.html`) to serve your bundles| -[common]: https://github.com/webpack/webpack/blob/master/lib/optimize/CommonsChunkPlugin.js [common-npm]: https://img.shields.io/npm/v/webpack.svg [extract]: https://github.com/webpack/extract-text-webpack-plugin [extract-npm]: https://img.shields.io/npm/v/extract-text-webpack-plugin.svg @@ -371,7 +369,7 @@ This is how we use the donations:

Premium Partners

Install

@@ -182,7 +182,7 @@ or are automatically applied via regex from your webpack configuration. |Name|Status|Description| |:--:|:----:|:----------| -|`
- + @@ -382,11 +380,11 @@ This is how we use the donations: Before we started using OpenCollective, donations were made anonymously. Now that we have made the switch, we would like to acknowledge these sponsors (and the ones who continue to donate using OpenCollective). If we've missed someone, please send us a PR, and we'll add you to this list.
- + [Google Angular Team](https://angular.io/), [Architects.io](http://architects.io/), -MoonMail -MoonMail +MONEI
From 800e7f967bc55a54e2fd57566dabc942104ecb72 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Tue, 6 Mar 2018 15:03:33 +0100 Subject: [PATCH 100/162] fix #6688 --- lib/optimize/ConcatenatedModule.js | 2 +- test/configCases/scope-hoisting/class-naming/index.js | 5 +++++ test/configCases/scope-hoisting/class-naming/module.js | 1 + test/configCases/scope-hoisting/class-naming/module2.js | 3 +++ .../scope-hoisting/class-naming/webpack.config.js | 5 +++++ 5 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 test/configCases/scope-hoisting/class-naming/index.js create mode 100644 test/configCases/scope-hoisting/class-naming/module.js create mode 100644 test/configCases/scope-hoisting/class-naming/module2.js create mode 100644 test/configCases/scope-hoisting/class-naming/webpack.config.js diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js index c8c12a5ce..2fede826a 100644 --- a/lib/optimize/ConcatenatedModule.js +++ b/lib/optimize/ConcatenatedModule.js @@ -173,10 +173,10 @@ const getSymbolsFromScope = (s, untilScope) => { const allUsedNames = new Set(); let scope = s; while (scope) { - if (untilScope === scope) break; for (const variable of scope.variables) { allUsedNames.add(variable.name); } + if (untilScope === scope) break; scope = scope.upper; } return allUsedNames; diff --git a/test/configCases/scope-hoisting/class-naming/index.js b/test/configCases/scope-hoisting/class-naming/index.js new file mode 100644 index 000000000..943a43e7f --- /dev/null +++ b/test/configCases/scope-hoisting/class-naming/index.js @@ -0,0 +1,5 @@ +import { Hello as t } from "./module2"; + +it("should rename classes correctly", () => { + new t(); +}); diff --git a/test/configCases/scope-hoisting/class-naming/module.js b/test/configCases/scope-hoisting/class-naming/module.js new file mode 100644 index 000000000..8875048be --- /dev/null +++ b/test/configCases/scope-hoisting/class-naming/module.js @@ -0,0 +1 @@ +export class Hello {} diff --git a/test/configCases/scope-hoisting/class-naming/module2.js b/test/configCases/scope-hoisting/class-naming/module2.js new file mode 100644 index 000000000..45434b08d --- /dev/null +++ b/test/configCases/scope-hoisting/class-naming/module2.js @@ -0,0 +1,3 @@ +import * as MODULE from "./module"; +let Hello = class Hello extends MODULE.Hello {} +export { Hello } diff --git a/test/configCases/scope-hoisting/class-naming/webpack.config.js b/test/configCases/scope-hoisting/class-naming/webpack.config.js new file mode 100644 index 000000000..59e948b12 --- /dev/null +++ b/test/configCases/scope-hoisting/class-naming/webpack.config.js @@ -0,0 +1,5 @@ +module.exports = { + optimization: { + concatenateModules: true + } +}; From 07c1f6d86f5e701f7df201687f6e99dd16e449d6 Mon Sep 17 00:00:00 2001 From: Maksim Nazarjev Date: Wed, 7 Mar 2018 00:56:31 +0300 Subject: [PATCH 101/162] Prevent webpack from running twice at a time --- lib/Compiler.js | 23 +++++++ lib/Watching.js | 1 + test/Compiler.test.js | 151 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/lib/Compiler.js b/lib/Compiler.js index 18c9307e9..4eda15ebe 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -129,17 +129,36 @@ class Compiler extends Tapable { this.context = context; this.requestShortener = new RequestShortener(context); + + this.running = false; } watch(watchOptions, handler) { + if (this.running) + return handler( + new Error( + "You ran Webpack twice. Each instance only supports a single concurrent compilation at a time." + ) + ); + + this.running = true; this.fileTimestamps = new Map(); this.contextTimestamps = new Map(); return new Watching(this, watchOptions, handler); } run(callback) { + if (this.running) + return callback( + new Error( + "You ran Webpack twice. Each instance only supports a single concurrent compilation at a time." + ) + ); + const startTime = Date.now(); + this.running = true; + const onCompiled = (err, compilation) => { if (err) return callback(err); @@ -148,6 +167,8 @@ class Compiler extends Tapable { stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { + this.running = false; + if (err) return callback(err); return callback(null, stats); }); @@ -181,6 +202,8 @@ class Compiler extends Tapable { stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { + this.running = false; + if (err) return callback(err); return callback(null, stats); }); diff --git a/lib/Watching.js b/lib/Watching.js index 19476af67..9b2c0fe07 100644 --- a/lib/Watching.js +++ b/lib/Watching.js @@ -168,6 +168,7 @@ class Watching { close(callback) { if (callback === undefined) callback = () => {}; + this.compiler.running = false; this.closed = true; if (this.watcher) { this.watcher.close(); diff --git a/test/Compiler.test.js b/test/Compiler.test.js index c1eba8d13..c633f29d4 100644 --- a/test/Compiler.test.js +++ b/test/Compiler.test.js @@ -246,7 +246,7 @@ describe("Compiler", () => { }); }); }); - it("should not emit on errors", function(done) { + it("should not emit on errors", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -282,5 +282,154 @@ describe("Compiler", () => { return done(new Error("Bundle should not be created on error")); done(); }); + }); + it("should not be run twice at a time (run)", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + compiler.run((err, stats) => { + if (err) return done(err); + }); + compiler.run((err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (watch)", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + compiler.watch({}, (err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (run - watch)", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + compiler.run((err, stats) => { + if (err) return done(err); + }); + compiler.watch({}, (err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (watch - run)", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + compiler.run((err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (instance cb)", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }, () => {}); + compiler.outputFileSystem = new MemoryFs(); + compiler.run((err, stats) => { + if (err) return done(); + }); + }); + it("should run again correctly after first compilation", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + compiler.run((err, stats) => { + if (err) return done(err); + + compiler.run((err, stats) => { + if (err) return done(err); + done() + }); + }); + }); + it("should watch again correctly after first compilation", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + compiler.run((err, stats) => { + if (err) return done(err); + + compiler.watch({}, (err, stats) => { + if (err) return done(err); + done() + }); + }); + }); + it("should run again correctly after first closed watch", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + const watching = compiler.watch({}, (err, stats) => { + if (err) return done(err); + done() + }); + watching.close(() => { + compiler.run((err, stats) => { + if (err) return done(err); + done() + }); + }) }); }); From 81a1cd8caad06f4c637dcbde7fa9d60609d8295c Mon Sep 17 00:00:00 2001 From: Maksim Nazarjev Date: Wed, 7 Mar 2018 01:31:14 +0300 Subject: [PATCH 102/162] Lint the tests --- test/Compiler.test.js | 95 ++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/test/Compiler.test.js b/test/Compiler.test.js index c633f29d4..3625cbdbc 100644 --- a/test/Compiler.test.js +++ b/test/Compiler.test.js @@ -246,7 +246,7 @@ describe("Compiler", () => { }); }); }); - it("should not emit on errors", function(done) { + it("should not emit on errors", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -282,8 +282,8 @@ describe("Compiler", () => { return done(new Error("Bundle should not be created on error")); done(); }); - }); - it("should not be run twice at a time (run)", function(done) { + }); + it("should not be run twice at a time (run)", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -301,7 +301,7 @@ describe("Compiler", () => { if (err) return done(); }); }); - it("should not be run twice at a time (watch)", function(done) { + it("should not be run twice at a time (watch)", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -318,8 +318,8 @@ describe("Compiler", () => { compiler.watch({}, (err, stats) => { if (err) return done(); }); - }); - it("should not be run twice at a time (run - watch)", function(done) { + }); + it("should not be run twice at a time (run - watch)", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -333,11 +333,11 @@ describe("Compiler", () => { compiler.run((err, stats) => { if (err) return done(err); }); - compiler.watch({}, (err, stats) => { + compiler.watch({}, (err, stats) => { if (err) return done(); }); }); - it("should not be run twice at a time (watch - run)", function(done) { + it("should not be run twice at a time (watch - run)", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -348,29 +348,32 @@ describe("Compiler", () => { } }); compiler.outputFileSystem = new MemoryFs(); - compiler.watch({}, (err, stats) => { + compiler.watch({}, (err, stats) => { if (err) return done(err); }); - compiler.run((err, stats) => { + compiler.run((err, stats) => { if (err) return done(); }); }); - it("should not be run twice at a time (instance cb)", function(done) { - const compiler = webpack({ - context: __dirname, - mode: "production", - entry: "./c", - output: { - path: "/", - filename: "bundle.js" - } - }, () => {}); + it("should not be run twice at a time (instance cb)", function(done) { + const compiler = webpack( + { + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }, + () => {} + ); compiler.outputFileSystem = new MemoryFs(); - compiler.run((err, stats) => { + compiler.run((err, stats) => { if (err) return done(); }); }); - it("should run again correctly after first compilation", function(done) { + it("should run again correctly after first compilation", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -381,16 +384,16 @@ describe("Compiler", () => { } }); compiler.outputFileSystem = new MemoryFs(); - compiler.run((err, stats) => { - if (err) return done(err); + compiler.run((err, stats) => { + if (err) return done(err); - compiler.run((err, stats) => { - if (err) return done(err); - done() - }); + compiler.run((err, stats) => { + if (err) return done(err); + done(); + }); }); }); - it("should watch again correctly after first compilation", function(done) { + it("should watch again correctly after first compilation", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -401,16 +404,16 @@ describe("Compiler", () => { } }); compiler.outputFileSystem = new MemoryFs(); - compiler.run((err, stats) => { - if (err) return done(err); + compiler.run((err, stats) => { + if (err) return done(err); - compiler.watch({}, (err, stats) => { - if (err) return done(err); - done() - }); + compiler.watch({}, (err, stats) => { + if (err) return done(err); + done(); + }); }); }); - it("should run again correctly after first closed watch", function(done) { + it("should run again correctly after first closed watch", function(done) { const compiler = webpack({ context: __dirname, mode: "production", @@ -421,15 +424,15 @@ describe("Compiler", () => { } }); compiler.outputFileSystem = new MemoryFs(); - const watching = compiler.watch({}, (err, stats) => { - if (err) return done(err); - done() - }); - watching.close(() => { - compiler.run((err, stats) => { - if (err) return done(err); - done() - }); - }) + const watching = compiler.watch({}, (err, stats) => { + if (err) return done(err); + done(); + }); + watching.close(() => { + compiler.run((err, stats) => { + if (err) return done(err); + done(); + }); + }); }); }); From 60a5edc48db185b3b9826769d7ba9bf084c8e32b Mon Sep 17 00:00:00 2001 From: Maksim Date: Wed, 7 Mar 2018 12:14:51 +0300 Subject: [PATCH 103/162] Wrap callback in compiler's run method --- lib/Compiler.js | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/Compiler.js b/lib/Compiler.js index 4eda15ebe..a59aa09e8 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -155,28 +155,32 @@ class Compiler extends Tapable { ) ); + const finalCallback = (err, stats) => { + this.running = false; + + if (callback !== undefined) return callback(err, stats); + }; + const startTime = Date.now(); this.running = true; const onCompiled = (err, compilation) => { - if (err) return callback(err); + if (err) return finalCallback(err); if (this.hooks.shouldEmit.call(compilation) === false) { const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { - this.running = false; - - if (err) return callback(err); - return callback(null, stats); + if (err) return finalCallback(err); + return finalCallback(null, stats); }); return; } this.emitAssets(compilation, err => { - if (err) return callback(err); + if (err) return finalCallback(err); if (compilation.hooks.needAdditionalPass.call()) { compilation.needAdditionalPass = true; @@ -185,10 +189,10 @@ class Compiler extends Tapable { stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { - if (err) return callback(err); + if (err) return finalCallback(err); this.hooks.additionalPass.callAsync(err => { - if (err) return callback(err); + if (err) return finalCallback(err); this.compile(onCompiled); }); }); @@ -196,29 +200,27 @@ class Compiler extends Tapable { } this.emitRecords(err => { - if (err) return callback(err); + if (err) return finalCallback(err); const stats = new Stats(compilation); stats.startTime = startTime; stats.endTime = Date.now(); this.hooks.done.callAsync(stats, err => { - this.running = false; - - if (err) return callback(err); - return callback(null, stats); + if (err) return finalCallback(err); + return finalCallback(null, stats); }); }); }); }; this.hooks.beforeRun.callAsync(this, err => { - if (err) return callback(err); + if (err) return finalCallback(err); this.hooks.run.callAsync(this, err => { - if (err) return callback(err); + if (err) return finalCallback(err); this.readRecords(err => { - if (err) return callback(err); + if (err) return finalCallback(err); this.compile(onCompiled); }); From 44e02f46d68d45a832a33645376de8989dd8755b Mon Sep 17 00:00:00 2001 From: Maksim Date: Wed, 7 Mar 2018 12:15:46 +0300 Subject: [PATCH 104/162] Wrap callback in watcher's close method --- lib/Watching.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/Watching.js b/lib/Watching.js index 9b2c0fe07..83ae72898 100644 --- a/lib/Watching.js +++ b/lib/Watching.js @@ -166,9 +166,12 @@ class Watching { } close(callback) { - if (callback === undefined) callback = () => {}; + const finalCallback = () => { + this.compiler.hooks.watchClose.call(); + this.compiler.running = false; + if (callback !== undefined) callback(); + }; - this.compiler.running = false; this.closed = true; if (this.watcher) { this.watcher.close(); @@ -180,13 +183,9 @@ class Watching { } if (this.running) { this.invalid = true; - this._done = () => { - this.compiler.hooks.watchClose.call(); - callback(); - }; + this._done = finalCallback; } else { - this.compiler.hooks.watchClose.call(); - callback(); + finalCallback(); } } } From e225d1005cb17994f024a6cfcfc2c8b5ac6218c4 Mon Sep 17 00:00:00 2001 From: Maksim Date: Wed, 7 Mar 2018 12:16:40 +0300 Subject: [PATCH 105/162] Fix compiler tests --- test/Compiler.test.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/Compiler.test.js b/test/Compiler.test.js index 3625cbdbc..f977ed562 100644 --- a/test/Compiler.test.js +++ b/test/Compiler.test.js @@ -426,7 +426,6 @@ describe("Compiler", () => { compiler.outputFileSystem = new MemoryFs(); const watching = compiler.watch({}, (err, stats) => { if (err) return done(err); - done(); }); watching.close(() => { compiler.run((err, stats) => { @@ -435,4 +434,25 @@ describe("Compiler", () => { }); }); }); + it("should watch again correctly after first closed watch", function(done) { + const compiler = webpack({ + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }); + compiler.outputFileSystem = new MemoryFs(); + const watching = compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + watching.close(() => { + compiler.watch({}, (err, stats) => { + if (err) return done(err); + done(); + }); + }); + }); }); From 9f60f506444c795f6db57f6513c72f4e77f7a874 Mon Sep 17 00:00:00 2001 From: Maksim Date: Wed, 7 Mar 2018 13:45:38 +0300 Subject: [PATCH 106/162] Prevent multi compiler from running twice at a time --- lib/MultiCompiler.js | 39 ++++++++++++-- lib/MultiWatching.js | 1 + test/MultiCompiler.test.js | 101 +++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 5 deletions(-) diff --git a/lib/MultiCompiler.js b/lib/MultiCompiler.js index 31a504dbb..574baeec0 100644 --- a/lib/MultiCompiler.js +++ b/lib/MultiCompiler.js @@ -53,6 +53,7 @@ module.exports = class MultiCompiler extends Tapable { } }); } + this.running = false; } get outputPath() { @@ -185,10 +186,24 @@ module.exports = class MultiCompiler extends Tapable { } watch(watchOptions, handler) { + if (this.running) + return handler( + new Error( + "You ran Webpack twice. Each instance only supports a single concurrent compilation at a time." + ) + ); + + const finalHandler = (err, stats) => { + this.running = false; + + if (handler !== undefined) handler(err, stats); + }; + let watchings = []; let allStats = this.compilers.map(() => null); let compilerStatus = this.compilers.map(() => false); - if (this.validateDependencies(handler)) { + if (this.validateDependencies(finalHandler)) { + this.running = true; this.runWithDependencies( this.compilers, (compiler, callback) => { @@ -199,7 +214,7 @@ module.exports = class MultiCompiler extends Tapable { ? watchOptions[compilerIdx] : watchOptions, (err, stats) => { - if (err) handler(err); + if (err) finalHandler(err); if (stats) { allStats[compilerIdx] = stats; compilerStatus[compilerIdx] = "new"; @@ -209,7 +224,7 @@ module.exports = class MultiCompiler extends Tapable { }); compilerStatus.fill(true); const multiStats = new MultiStats(freshStats); - handler(null, multiStats); + finalHandler(null, multiStats); } } if (firstRun && !err) { @@ -230,8 +245,22 @@ module.exports = class MultiCompiler extends Tapable { } run(callback) { + if (this.running) + return callback( + new Error( + "You ran Webpack twice. Each instance only supports a single concurrent compilation at a time." + ) + ); + + const finalCallback = (err, stats) => { + this.running = false; + + if (callback !== undefined) return callback(err, stats); + }; + const allStats = this.compilers.map(() => null); if (this.validateDependencies(callback)) { + this.running = true; this.runWithDependencies( this.compilers, (compiler, callback) => { @@ -243,8 +272,8 @@ module.exports = class MultiCompiler extends Tapable { }); }, err => { - if (err) return callback(err); - callback(null, new MultiStats(allStats)); + if (err) return finalCallback(err); + finalCallback(null, new MultiStats(allStats)); } ); } diff --git a/lib/MultiWatching.js b/lib/MultiWatching.js index 80a6a4a53..48e012c87 100644 --- a/lib/MultiWatching.js +++ b/lib/MultiWatching.js @@ -27,6 +27,7 @@ class MultiWatching { err => { this.compiler.hooks.watchClose.call(); if (typeof callback === "function") { + this.compiler.running = false; callback(err); } } diff --git a/test/MultiCompiler.test.js b/test/MultiCompiler.test.js index 2f2f0dad0..bb3a11f7e 100644 --- a/test/MultiCompiler.test.js +++ b/test/MultiCompiler.test.js @@ -52,4 +52,105 @@ describe("MultiCompiler", function() { } }); }); + + it("should not be run twice at a time (run)", function(done) { + const compiler = createMultiCompiler(); + compiler.run((err, stats) => { + if (err) return done(err); + }); + compiler.run((err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (watch)", function(done) { + const compiler = createMultiCompiler(); + compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + compiler.watch({}, (err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (run - watch)", function(done) { + const compiler = createMultiCompiler(); + compiler.run((err, stats) => { + if (err) return done(err); + }); + compiler.watch({}, (err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (watch - run)", function(done) { + const compiler = createMultiCompiler(); + compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + compiler.run((err, stats) => { + if (err) return done(); + }); + }); + it("should not be run twice at a time (instance cb)", function(done) { + const compiler = webpack( + { + context: __dirname, + mode: "production", + entry: "./c", + output: { + path: "/", + filename: "bundle.js" + } + }, + () => {} + ); + compiler.outputFileSystem = new MemoryFs(); + compiler.run((err, stats) => { + if (err) return done(); + }); + }); + it("should run again correctly after first compilation", function(done) { + const compiler = createMultiCompiler(); + compiler.run((err, stats) => { + if (err) return done(err); + + compiler.run((err, stats) => { + if (err) return done(err); + done(); + }); + }); + }); + it("should watch again correctly after first compilation", function(done) { + const compiler = createMultiCompiler(); + compiler.run((err, stats) => { + if (err) return done(err); + + compiler.watch({}, (err, stats) => { + if (err) return done(err); + done(); + }); + }); + }); + it("should run again correctly after first closed watch", function(done) { + const compiler = createMultiCompiler(); + const watching = compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + watching.close(() => { + compiler.run((err, stats) => { + if (err) return done(err); + done(); + }); + }); + }); + it("should watch again correctly after first closed watch", function(done) { + const compiler = createMultiCompiler(); + const watching = compiler.watch({}, (err, stats) => { + if (err) return done(err); + }); + watching.close(() => { + compiler.watch({}, (err, stats) => { + if (err) return done(err); + done(); + }); + }); + }); }); From 4d6835012849d782e25864ac7653928ebea826db Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 7 Mar 2018 15:31:12 +0100 Subject: [PATCH 107/162] fix bug where modules are put into the wrong chunk fixes #6696 --- lib/optimize/SplitChunksPlugin.js | 2 ++ test/statsCases/split-chunks-issue-6696/a.js | 1 + test/statsCases/split-chunks-issue-6696/b.js | 1 + .../split-chunks-issue-6696/expected.txt | 15 ++++++++ .../split-chunks-issue-6696/index.js | 3 ++ .../split-chunks-issue-6696/node_modules/x.js | 1 + .../split-chunks-issue-6696/node_modules/y.js | 1 + .../split-chunks-issue-6696/webpack.config.js | 34 +++++++++++++++++++ 8 files changed, 58 insertions(+) create mode 100644 test/statsCases/split-chunks-issue-6696/a.js create mode 100644 test/statsCases/split-chunks-issue-6696/b.js create mode 100644 test/statsCases/split-chunks-issue-6696/expected.txt create mode 100644 test/statsCases/split-chunks-issue-6696/index.js create mode 100644 test/statsCases/split-chunks-issue-6696/node_modules/x.js create mode 100644 test/statsCases/split-chunks-issue-6696/node_modules/y.js create mode 100644 test/statsCases/split-chunks-issue-6696/webpack.config.js diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index c65eaa4d1..8626d4b17 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -304,6 +304,8 @@ module.exports = class SplitChunksPlugin { chunk => !chunk.canBeInitial() ) : Array.from(chunkCombination); + // Break if minimum number of chunks is not reached + if (selectedChunks.length < cacheGroup.minChunks) continue; // Determine name for split chunk const name = cacheGroup.getName( module, diff --git a/test/statsCases/split-chunks-issue-6696/a.js b/test/statsCases/split-chunks-issue-6696/a.js new file mode 100644 index 000000000..856f26b34 --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/a.js @@ -0,0 +1 @@ +import "x"; diff --git a/test/statsCases/split-chunks-issue-6696/b.js b/test/statsCases/split-chunks-issue-6696/b.js new file mode 100644 index 000000000..856f26b34 --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/b.js @@ -0,0 +1 @@ +import "x"; diff --git a/test/statsCases/split-chunks-issue-6696/expected.txt b/test/statsCases/split-chunks-issue-6696/expected.txt new file mode 100644 index 000000000..783724c34 --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/expected.txt @@ -0,0 +1,15 @@ +Entrypoint main = vendors.js main.js +chunk {0} async-a.js (async-a) 32 bytes <{2}> <{3}> [rendered] + > ./a [3] ./index.js 2:0-47 + [0] ./node_modules/x.js 20 bytes {0} {1} [built] + [1] ./a.js 12 bytes {0} [built] +chunk {1} async-b.js (async-b) 32 bytes <{2}> <{3}> [rendered] + > ./b [3] ./index.js 3:0-47 + [0] ./node_modules/x.js 20 bytes {0} {1} [built] + [2] ./b.js 12 bytes {1} [built] +chunk {2} main.js (main) 110 bytes ={3}= >{0}< >{1}< [entry] [rendered] + > ./ main + [3] ./index.js 110 bytes {2} [built] +chunk {3} vendors.js (vendors) 20 bytes ={2}= >{0}< >{1}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors) + > ./ main + [4] ./node_modules/y.js 20 bytes {3} [built] \ No newline at end of file diff --git a/test/statsCases/split-chunks-issue-6696/index.js b/test/statsCases/split-chunks-issue-6696/index.js new file mode 100644 index 000000000..bba35d269 --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/index.js @@ -0,0 +1,3 @@ +import "y"; +import(/* webpackChunkName: "async-a" */ "./a"); +import(/* webpackChunkName: "async-b" */ "./b"); diff --git a/test/statsCases/split-chunks-issue-6696/node_modules/x.js b/test/statsCases/split-chunks-issue-6696/node_modules/x.js new file mode 100644 index 000000000..3fd5ecc7a --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/node_modules/x.js @@ -0,0 +1 @@ +export default "x"; diff --git a/test/statsCases/split-chunks-issue-6696/node_modules/y.js b/test/statsCases/split-chunks-issue-6696/node_modules/y.js new file mode 100644 index 000000000..413e7c09d --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/node_modules/y.js @@ -0,0 +1 @@ +export default "y"; diff --git a/test/statsCases/split-chunks-issue-6696/webpack.config.js b/test/statsCases/split-chunks-issue-6696/webpack.config.js new file mode 100644 index 000000000..6a74b935b --- /dev/null +++ b/test/statsCases/split-chunks-issue-6696/webpack.config.js @@ -0,0 +1,34 @@ +const stats = { + hash: false, + timings: false, + builtAt: false, + assets: false, + chunks: true, + chunkOrigins: true, + entrypoints: true, + modules: false +}; +module.exports = { + name: "default", + mode: "production", + entry: { + main: "./" + }, + output: { + filename: "[name].js" + }, + optimization: { + splitChunks: { + cacheGroups: { + default: false, + vendors: { + test: /[\\/]node_modules[\\/]/, + chunks: "initial", + enforce: true, + name: "vendors" + } + } + } + }, + stats +}; From 41bb63ad69d0f32c042e74e732cb045b5966c452 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 7 Mar 2018 16:37:44 +0100 Subject: [PATCH 108/162] 4.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 17450f4ea..3d311780a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "4.1.0", + "version": "4.1.1", "author": "Tobias Koppers @sokra", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "license": "MIT", From cdeffb39b06c2a5d56af9e34576d5de66b6d6a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bazyli=20Brzo=CC=81ska?= Date: Wed, 7 Mar 2018 20:28:14 +0100 Subject: [PATCH 109/162] fix(ProfilingPlugin): only expose the end method of fsStream --- lib/debug/ProfilingPlugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/debug/ProfilingPlugin.js b/lib/debug/ProfilingPlugin.js index 2c05c368b..57e49b002 100644 --- a/lib/debug/ProfilingPlugin.js +++ b/lib/debug/ProfilingPlugin.js @@ -73,7 +73,7 @@ class Profiler { /** * @param {string} outputPath The location where to write the log. - * @returns {{trace: ?, counter: number, profiler: Profiler, fsStream: WriteStream}} The trace object + * @returns {{trace: ?, counter: number, profiler: Profiler, end: Function}} The trace object */ function createTrace(outputPath) { const trace = new Trace({ @@ -121,7 +121,7 @@ function createTrace(outputPath) { trace, counter, profiler, - fsStream + end: (callback) => fsStream.end(callback) }; } @@ -181,7 +181,7 @@ class ProfilingPlugin { if (parsedResults === undefined) { tracer.profiler.destroy(); tracer.trace.flush(); - tracer.fsStream.end(callback); + tracer.end(callback); return; } @@ -229,7 +229,7 @@ class ProfilingPlugin { tracer.profiler.destroy(); tracer.trace.flush(); - tracer.fsStream.end(callback); + tracer.end(callback); }); } ); From bd043f8e26faeaaabf03cd71dc18c6e96fddc03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bazyli=20Brzo=CC=81ska?= Date: Wed, 7 Mar 2018 21:09:09 +0100 Subject: [PATCH 110/162] fix lint --- lib/debug/ProfilingPlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/debug/ProfilingPlugin.js b/lib/debug/ProfilingPlugin.js index 57e49b002..ab82ca090 100644 --- a/lib/debug/ProfilingPlugin.js +++ b/lib/debug/ProfilingPlugin.js @@ -121,7 +121,7 @@ function createTrace(outputPath) { trace, counter, profiler, - end: (callback) => fsStream.end(callback) + end: callback => fsStream.end(callback) }; } From 36db321e9c23c16ff227fb3d029d851cd8f2729f Mon Sep 17 00:00:00 2001 From: Manuel Bauer Date: Fri, 9 Mar 2018 10:12:23 +0100 Subject: [PATCH 111/162] Added chunkFilenameDelimiter option for SplitChunksPlugin --- lib/WebpackOptionsDefaulter.js | 1 + lib/WebpackOptionsValidationError.js | 2 +- lib/optimize/SplitChunksPlugin.js | 9 +++++---- schemas/WebpackOptions.json | 5 +++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index e6c9c44d0..69c4adddb 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -210,6 +210,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("optimization.splitChunks.minSize", 30000); this.set("optimization.splitChunks.minChunks", 1); this.set("optimization.splitChunks.maxAsyncRequests", 5); + this.set("optimization.splitChunks.chunkFilenameDelimiter", "~"); this.set("optimization.splitChunks.maxInitialRequests", 3); this.set("optimization.splitChunks.name", true); this.set("optimization.splitChunks.cacheGroups", {}); diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index 4d8abd7d5..e7f3f3802 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -65,7 +65,7 @@ class WebpackOptionsValidationError extends WebpackError { this.name = "WebpackOptionsValidationError"; this.message = - "Invalid configuration object. " + + "Invalid configuration object. :( " + "Webpack has been initialised using a configuration object that does not match the API schema.\n" + validationErrors .map( diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 8626d4b17..7e97a392b 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -94,7 +94,8 @@ module.exports = class SplitChunksPlugin { filename: options.filename || undefined, getCacheGroups: SplitChunksPlugin.normalizeCacheGroups( options.cacheGroups - ) + ), + chunkFilenameDelimiter: options.chunkFilenameDelimiter || '~' }; } @@ -105,15 +106,15 @@ module.exports = class SplitChunksPlugin { if (!names.every(Boolean)) return; names.sort(); let name = - (cacheGroup && cacheGroup !== "default" ? cacheGroup + "~" : "") + - names.join("~"); + (cacheGroup && cacheGroup !== "default" ? cacheGroup + this.options.chunkFilenameDelimiter : "") + + names.join(this.options.chunkFilenameDelimiter); // Filenames and paths can't be too long otherwise an // ENAMETOOLONG error is raised. If the generated name if too // long, it is truncated and a hash is appended. The limit has // been set to 100 to prevent `[name].[chunkhash].[ext]` from // generating a 256+ character string. if (name.length > 100) { - name = name.slice(0, 100) + "~" + hashFilename(name); + name = name.slice(0, 100) + this.options.chunkFilenameDelimiter + hashFilename(name); } return name; }; diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index b8dbdd388..4963b0b3a 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -1382,6 +1382,11 @@ "type": "string", "minLength": 1 }, + "chunkFilenameDelimiter": { + "description": "Sets the filename delimiter for created chunks", + "type": "string", + "minLength": 1 + }, "cacheGroups": { "description": "Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks)", "type": "object", From b803c649eeaa9617353ea4db719381116a579044 Mon Sep 17 00:00:00 2001 From: Manuel Bauer Date: Fri, 9 Mar 2018 10:28:21 +0100 Subject: [PATCH 112/162] Added chunkFilenameDelimiter option for SplitChunksPlugin: Fixed parameter --- lib/optimize/SplitChunksPlugin.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 7e97a392b..dd22ad9a2 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -84,37 +84,39 @@ module.exports = class SplitChunksPlugin { } static normalizeOptions(options = {}) { + const chunkFilenameDelimiter = options.chunkFilenameDelimiter || '~'; + return { chunks: options.chunks || "all", minSize: options.minSize || 0, minChunks: options.minChunks || 1, maxAsyncRequests: options.maxAsyncRequests || 1, maxInitialRequests: options.maxInitialRequests || 1, - getName: SplitChunksPlugin.normalizeName(options.name) || (() => {}), + getName: SplitChunksPlugin.normalizeName(options.name, chunkFilenameDelimiter) || (() => {}), filename: options.filename || undefined, getCacheGroups: SplitChunksPlugin.normalizeCacheGroups( - options.cacheGroups + options.cacheGroups, chunkFilenameDelimiter ), - chunkFilenameDelimiter: options.chunkFilenameDelimiter || '~' + chunkFilenameDelimiter: chunkFilenameDelimiter }; } - static normalizeName(option) { + static normalizeName(option, chunkFilenameDelimiter) { if (option === true) { const fn = (module, chunks, cacheGroup) => { const names = chunks.map(c => c.name); if (!names.every(Boolean)) return; names.sort(); let name = - (cacheGroup && cacheGroup !== "default" ? cacheGroup + this.options.chunkFilenameDelimiter : "") + - names.join(this.options.chunkFilenameDelimiter); + (cacheGroup && cacheGroup !== "default" ? cacheGroup + chunkFilenameDelimiter : "") + + names.join(chunkFilenameDelimiter); // Filenames and paths can't be too long otherwise an // ENAMETOOLONG error is raised. If the generated name if too // long, it is truncated and a hash is appended. The limit has // been set to 100 to prevent `[name].[chunkhash].[ext]` from // generating a 256+ character string. if (name.length > 100) { - name = name.slice(0, 100) + this.options.chunkFilenameDelimiter + hashFilename(name); + name = name.slice(0, 100) + chunkFilenameDelimiter + hashFilename(name); } return name; }; @@ -129,7 +131,7 @@ module.exports = class SplitChunksPlugin { if (typeof option === "function") return option; } - static normalizeCacheGroups(cacheGroups) { + static normalizeCacheGroups(cacheGroups, chunkFilenameDelimiter) { if (typeof cacheGroups === "function") { return cacheGroups; } @@ -164,7 +166,7 @@ module.exports = class SplitChunksPlugin { results.push({ key: key, priority: option.priority, - getName: SplitChunksPlugin.normalizeName(option.name), + getName: SplitChunksPlugin.normalizeName(option.name, chunkFilenameDelimiter), chunks: option.chunks, enforce: option.enforce, minSize: option.minSize, From ddb78d7c0ad0da8c793a270830468bdef9099eda Mon Sep 17 00:00:00 2001 From: Manuel Bauer Date: Fri, 9 Mar 2018 10:29:58 +0100 Subject: [PATCH 113/162] Added chunkFilenameDelimiter option for SplitChunksPlugin: Fixed Typo --- lib/WebpackOptionsValidationError.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/WebpackOptionsValidationError.js b/lib/WebpackOptionsValidationError.js index e7f3f3802..4d8abd7d5 100644 --- a/lib/WebpackOptionsValidationError.js +++ b/lib/WebpackOptionsValidationError.js @@ -65,7 +65,7 @@ class WebpackOptionsValidationError extends WebpackError { this.name = "WebpackOptionsValidationError"; this.message = - "Invalid configuration object. :( " + + "Invalid configuration object. " + "Webpack has been initialised using a configuration object that does not match the API schema.\n" + validationErrors .map( From 085d2885e4d40bee87663f0bb7f807da1fbbca40 Mon Sep 17 00:00:00 2001 From: Manuel Bauer Date: Fri, 9 Mar 2018 14:27:19 +0100 Subject: [PATCH 114/162] Added chunkFilenameDelimiter option for SplitChunksPlugin: Added tests and fixed code style --- lib/optimize/SplitChunksPlugin.js | 32 +- .../chunk-filename-delimiter-default/a.js | 3 + .../chunk-filename-delimiter-default/b.js | 3 + .../chunk-filename-delimiter-default/c.js | 3 + .../commons.js | 666 ++++++++++++++++++ .../chunk-filename-delimiter-default/index.js | 16 + .../test.config.js | 5 + .../webpack.config.js | 17 + .../chunk-filename-delimiter/a.js | 3 + .../chunk-filename-delimiter/b.js | 3 + .../chunk-filename-delimiter/c.js | 3 + .../chunk-filename-delimiter/commons.js | 666 ++++++++++++++++++ .../chunk-filename-delimiter/index.js | 16 + .../chunk-filename-delimiter/test.config.js | 5 + .../webpack.config.js | 22 + 15 files changed, 1452 insertions(+), 11 deletions(-) create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/a.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/b.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/c.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/index.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/test.config.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/a.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/b.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/c.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/commons.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/index.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/test.config.js create mode 100644 test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index dd22ad9a2..daf42b933 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -84,7 +84,7 @@ module.exports = class SplitChunksPlugin { } static normalizeOptions(options = {}) { - const chunkFilenameDelimiter = options.chunkFilenameDelimiter || '~'; + const chunkFilenameDelimiter = options.chunkFilenameDelimiter || "~"; return { chunks: options.chunks || "all", @@ -92,31 +92,38 @@ module.exports = class SplitChunksPlugin { minChunks: options.minChunks || 1, maxAsyncRequests: options.maxAsyncRequests || 1, maxInitialRequests: options.maxInitialRequests || 1, - getName: SplitChunksPlugin.normalizeName(options.name, chunkFilenameDelimiter) || (() => {}), + getName: + SplitChunksPlugin.normalizeName({ + option: options.name, + chunkFilenameDelimiter + }) || (() => {}), filename: options.filename || undefined, - getCacheGroups: SplitChunksPlugin.normalizeCacheGroups( - options.cacheGroups, chunkFilenameDelimiter - ), + getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({ + cacheGroups: options.cacheGroups, + chunkFilenameDelimiter + }), chunkFilenameDelimiter: chunkFilenameDelimiter }; } - static normalizeName(option, chunkFilenameDelimiter) { + static normalizeName({ option, chunkFilenameDelimiter }) { if (option === true) { const fn = (module, chunks, cacheGroup) => { const names = chunks.map(c => c.name); if (!names.every(Boolean)) return; names.sort(); let name = - (cacheGroup && cacheGroup !== "default" ? cacheGroup + chunkFilenameDelimiter : "") + - names.join(chunkFilenameDelimiter); + (cacheGroup && cacheGroup !== "default" + ? cacheGroup + chunkFilenameDelimiter + : "") + names.join(chunkFilenameDelimiter); // Filenames and paths can't be too long otherwise an // ENAMETOOLONG error is raised. If the generated name if too // long, it is truncated and a hash is appended. The limit has // been set to 100 to prevent `[name].[chunkhash].[ext]` from // generating a 256+ character string. if (name.length > 100) { - name = name.slice(0, 100) + chunkFilenameDelimiter + hashFilename(name); + name = + name.slice(0, 100) + chunkFilenameDelimiter + hashFilename(name); } return name; }; @@ -131,7 +138,7 @@ module.exports = class SplitChunksPlugin { if (typeof option === "function") return option; } - static normalizeCacheGroups(cacheGroups, chunkFilenameDelimiter) { + static normalizeCacheGroups({ cacheGroups, chunkFilenameDelimiter }) { if (typeof cacheGroups === "function") { return cacheGroups; } @@ -166,7 +173,10 @@ module.exports = class SplitChunksPlugin { results.push({ key: key, priority: option.priority, - getName: SplitChunksPlugin.normalizeName(option.name, chunkFilenameDelimiter), + getName: SplitChunksPlugin.normalizeName({ + option: option.name, + chunkFilenameDelimiter + }), chunks: option.chunks, enforce: option.enforce, minSize: option.minSize, diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/a.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/a.js new file mode 100644 index 000000000..bebcbefc7 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/a.js @@ -0,0 +1,3 @@ +const c = require("./commons"); + +module.exports = "a" + c; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/b.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/b.js new file mode 100644 index 000000000..a072377a0 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/b.js @@ -0,0 +1,3 @@ +const c = require("./commons"); + +module.exports = "b" + c; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/c.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/c.js new file mode 100644 index 000000000..586ed0971 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/c.js @@ -0,0 +1,3 @@ +const c = require("./commons"); + +module.exports = "c" + c; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js new file mode 100644 index 000000000..f8f61c315 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js @@ -0,0 +1,666 @@ +/* Large module to trigger chunk generation */ +module.exports = + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy"; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/index.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/index.js new file mode 100644 index 000000000..15b22fc95 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/index.js @@ -0,0 +1,16 @@ +require("should"); + +it("should run", function() { + Promise.all( + [ + import(/* webpackChunkName: "a" */ "./a"), + import(/* webpackChunkName: "b" */ "./b"), + import(/* webpackChunkName: "c" */ "./c") + ] + ); + + const files = require("fs").readdirSync(__dirname); + const hasFile = files.indexOf('a~b~c.bundle.js') !== -1; + + hasFile.should.be.eql(true); +}); diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/test.config.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/test.config.js new file mode 100644 index 000000000..65ddf7b1d --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function(i, options) { + return ["main.js"]; + } +}; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js new file mode 100644 index 000000000..e42172090 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js @@ -0,0 +1,17 @@ +const SplitChunksPlugin = require("../../../../lib/optimize/SplitChunksPlugin"); + +module.exports = { + entry: { + main: "./index" + }, + node: { + __dirname: false, + __filename: false + }, + output: { + filename: "[name].js", + chunkFilename: "[name].bundle.js", + jsonpFunction: "_load_chunk" + }, + plugins: [new SplitChunksPlugin()] +}; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/a.js b/test/configCases/split-chunks/chunk-filename-delimiter/a.js new file mode 100644 index 000000000..bebcbefc7 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/a.js @@ -0,0 +1,3 @@ +const c = require("./commons"); + +module.exports = "a" + c; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/b.js b/test/configCases/split-chunks/chunk-filename-delimiter/b.js new file mode 100644 index 000000000..a072377a0 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/b.js @@ -0,0 +1,3 @@ +const c = require("./commons"); + +module.exports = "b" + c; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/c.js b/test/configCases/split-chunks/chunk-filename-delimiter/c.js new file mode 100644 index 000000000..586ed0971 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/c.js @@ -0,0 +1,3 @@ +const c = require("./commons"); + +module.exports = "c" + c; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/commons.js b/test/configCases/split-chunks/chunk-filename-delimiter/commons.js new file mode 100644 index 000000000..f8f61c315 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/commons.js @@ -0,0 +1,666 @@ +/* Large module to trigger chunk generation */ +module.exports = + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy" + + "All Work and No Play Makes Jack a Dull Boy"; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/index.js b/test/configCases/split-chunks/chunk-filename-delimiter/index.js new file mode 100644 index 000000000..47a30f17f --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/index.js @@ -0,0 +1,16 @@ +require("should"); + +it("should run", function() { + Promise.all( + [ + import(/* webpackChunkName: "a" */ "./a"), + import(/* webpackChunkName: "b" */ "./b"), + import(/* webpackChunkName: "c" */ "./c") + ] + ); + + const files = require("fs").readdirSync(__dirname); + const hasFile = files.indexOf('a-b-c.bundle.js') !== -1; + + hasFile.should.be.eql(true); +}); diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/test.config.js b/test/configCases/split-chunks/chunk-filename-delimiter/test.config.js new file mode 100644 index 000000000..65ddf7b1d --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function(i, options) { + return ["main.js"]; + } +}; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js b/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js new file mode 100644 index 000000000..2aadaa556 --- /dev/null +++ b/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js @@ -0,0 +1,22 @@ +const SplitChunksPlugin = require("../../../../lib/optimize/SplitChunksPlugin"); + +module.exports = { + entry: { + main: "./index" + }, + node: { + __dirname: false, + __filename: false + }, + output: { + filename: "[name].js", + chunkFilename: "[name].bundle.js", + jsonpFunction: "_load_chunk" + }, + optimization: { + splitChunks: { + chunkFilenameDelimiter: "-" + } + }, + plugins: [new SplitChunksPlugin()] +}; From 7a191904f6357e5cf4c563dfbfcf83d606bb9c3d Mon Sep 17 00:00:00 2001 From: Fernando Montoya Date: Fri, 9 Mar 2018 16:45:42 +0100 Subject: [PATCH 115/162] bot: Encapsulate output logs in details tag --- open-bot.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/open-bot.yaml b/open-bot.yaml index 8b50d3e50..b1b713a2c 100644 --- a/open-bot.yaml +++ b/open-bot.yaml @@ -85,10 +85,11 @@ rules: identifier: "ci-result" message: |- @{{commit.author.login}} Please review the following output log for errors: - +
``` text {{{logResult}}} ``` +
See [complete report here]({{status.target_url}}). set: From 37b4ecf4e32bb26a7ad386c8d4c4718e501616d2 Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 11 Mar 2018 03:29:54 +0100 Subject: [PATCH 116/162] Only declare mocha globals inside dir --- .eslintrc.js | 1 - test/.eslintrc.js | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 test/.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 12149e7f6..ff735cc64 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,7 +8,6 @@ module.exports = { "env": { "node": true, "es6": true, - "mocha": true, }, "parserOptions": { "ecmaVersion": 2017 }, "rules": { diff --git a/test/.eslintrc.js b/test/.eslintrc.js new file mode 100644 index 000000000..060395653 --- /dev/null +++ b/test/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + "env": { + "mocha": true, + } +}; From fbeb415ad4c11dbe9c88e446890f5d677a1e110b Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 11 Mar 2018 04:15:29 +0100 Subject: [PATCH 117/162] Prettify --- test/.eslintrc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/.eslintrc.js b/test/.eslintrc.js index 060395653..79a6c62ab 100644 --- a/test/.eslintrc.js +++ b/test/.eslintrc.js @@ -1,5 +1,5 @@ module.exports = { - "env": { - "mocha": true, + env: { + mocha: true } }; From bda8d5281051a2baf84fc61761a8a7cad02c05d9 Mon Sep 17 00:00:00 2001 From: Manuel Bauer Date: Mon, 12 Mar 2018 10:07:31 +0100 Subject: [PATCH 118/162] Added chunkFilenameDelimiter option for SplitChunksPlugin: Applied requested changes --- lib/WebpackOptionsDefaulter.js | 2 +- lib/optimize/SplitChunksPlugin.js | 31 +- schemas/WebpackOptions.json | 4 +- .../commons.js | 666 +---------------- .../webpack.config.js | 8 +- .../chunk-filename-delimiter/commons.js | 668 +----------------- .../webpack.config.js | 8 +- 7 files changed, 28 insertions(+), 1359 deletions(-) diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index 69c4adddb..0e6e9dccd 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -210,7 +210,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("optimization.splitChunks.minSize", 30000); this.set("optimization.splitChunks.minChunks", 1); this.set("optimization.splitChunks.maxAsyncRequests", 5); - this.set("optimization.splitChunks.chunkFilenameDelimiter", "~"); + this.set("optimization.splitChunks.automaticNameDelimiter", "~"); this.set("optimization.splitChunks.maxInitialRequests", 3); this.set("optimization.splitChunks.name", true); this.set("optimization.splitChunks.cacheGroups", {}); diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index daf42b933..59c7dc8c1 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -84,8 +84,6 @@ module.exports = class SplitChunksPlugin { } static normalizeOptions(options = {}) { - const chunkFilenameDelimiter = options.chunkFilenameDelimiter || "~"; - return { chunks: options.chunks || "all", minSize: options.minSize || 0, @@ -94,28 +92,27 @@ module.exports = class SplitChunksPlugin { maxInitialRequests: options.maxInitialRequests || 1, getName: SplitChunksPlugin.normalizeName({ - option: options.name, - chunkFilenameDelimiter + name: options.name, + automaticNameDelimiter: options.automaticNameDelimiter }) || (() => {}), filename: options.filename || undefined, getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({ cacheGroups: options.cacheGroups, - chunkFilenameDelimiter - }), - chunkFilenameDelimiter: chunkFilenameDelimiter + automaticNameDelimiter: options.automaticNameDelimiter + }) }; } - static normalizeName({ option, chunkFilenameDelimiter }) { - if (option === true) { + static normalizeName({ name, automaticNameDelimiter }) { + if (name === true) { const fn = (module, chunks, cacheGroup) => { const names = chunks.map(c => c.name); if (!names.every(Boolean)) return; names.sort(); let name = (cacheGroup && cacheGroup !== "default" - ? cacheGroup + chunkFilenameDelimiter - : "") + names.join(chunkFilenameDelimiter); + ? cacheGroup + automaticNameDelimiter + : "") + names.join(automaticNameDelimiter); // Filenames and paths can't be too long otherwise an // ENAMETOOLONG error is raised. If the generated name if too // long, it is truncated and a hash is appended. The limit has @@ -123,7 +120,7 @@ module.exports = class SplitChunksPlugin { // generating a 256+ character string. if (name.length > 100) { name = - name.slice(0, 100) + chunkFilenameDelimiter + hashFilename(name); + name.slice(0, 100) + automaticNameDelimiter + hashFilename(name); } return name; }; @@ -131,14 +128,14 @@ module.exports = class SplitChunksPlugin { } if (typeof option === "string") { const fn = () => { - return option; + return name; }; return fn; } - if (typeof option === "function") return option; + if (typeof option === "function") return name; } - static normalizeCacheGroups({ cacheGroups, chunkFilenameDelimiter }) { + static normalizeCacheGroups({ cacheGroups, automaticNameDelimiter }) { if (typeof cacheGroups === "function") { return cacheGroups; } @@ -174,8 +171,8 @@ module.exports = class SplitChunksPlugin { key: key, priority: option.priority, getName: SplitChunksPlugin.normalizeName({ - option: option.name, - chunkFilenameDelimiter + name: option.name, + automaticNameDelimiter }), chunks: option.chunks, enforce: option.enforce, diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index 4963b0b3a..c678a5d71 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -1382,8 +1382,8 @@ "type": "string", "minLength": 1 }, - "chunkFilenameDelimiter": { - "description": "Sets the filename delimiter for created chunks", + "automaticNameDelimiter": { + "description": "Sets the name delimiter for created chunks", "type": "string", "minLength": 1 }, diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js index f8f61c315..92b4a4ef5 100644 --- a/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/commons.js @@ -1,666 +1,2 @@ /* Large module to trigger chunk generation */ -module.exports = - "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy"; +module.exports = "commons"; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js b/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js index e42172090..e5f361c51 100644 --- a/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js +++ b/test/configCases/split-chunks/chunk-filename-delimiter-default/webpack.config.js @@ -1,5 +1,3 @@ -const SplitChunksPlugin = require("../../../../lib/optimize/SplitChunksPlugin"); - module.exports = { entry: { main: "./index" @@ -13,5 +11,9 @@ module.exports = { chunkFilename: "[name].bundle.js", jsonpFunction: "_load_chunk" }, - plugins: [new SplitChunksPlugin()] + optimization: { + splitChunks: { + minSize: 1 + } + } }; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/commons.js b/test/configCases/split-chunks/chunk-filename-delimiter/commons.js index f8f61c315..622e9f1e1 100644 --- a/test/configCases/split-chunks/chunk-filename-delimiter/commons.js +++ b/test/configCases/split-chunks/chunk-filename-delimiter/commons.js @@ -1,666 +1,2 @@ -/* Large module to trigger chunk generation */ -module.exports = - "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy" - + "All Work and No Play Makes Jack a Dull Boy"; + +module.exports = "commons"; diff --git a/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js b/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js index 2aadaa556..2a3cd9423 100644 --- a/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js +++ b/test/configCases/split-chunks/chunk-filename-delimiter/webpack.config.js @@ -1,5 +1,3 @@ -const SplitChunksPlugin = require("../../../../lib/optimize/SplitChunksPlugin"); - module.exports = { entry: { main: "./index" @@ -15,8 +13,8 @@ module.exports = { }, optimization: { splitChunks: { - chunkFilenameDelimiter: "-" + automaticNameDelimiter: "-", + minSize: 1 } - }, - plugins: [new SplitChunksPlugin()] + } }; From 771bf859a66315de0826c9e23798fe41ee70fd30 Mon Sep 17 00:00:00 2001 From: Manuel Bauer Date: Mon, 12 Mar 2018 10:32:46 +0100 Subject: [PATCH 119/162] Added chunkFilenameDelimiter option for SplitChunksPlugin: Fixed test issue --- lib/optimize/SplitChunksPlugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js index 59c7dc8c1..ea35dd9dc 100644 --- a/lib/optimize/SplitChunksPlugin.js +++ b/lib/optimize/SplitChunksPlugin.js @@ -126,13 +126,13 @@ module.exports = class SplitChunksPlugin { }; return fn; } - if (typeof option === "string") { + if (typeof name === "string") { const fn = () => { return name; }; return fn; } - if (typeof option === "function") return name; + if (typeof name === "function") return name; } static normalizeCacheGroups({ cacheGroups, automaticNameDelimiter }) { From 3ac042a5a86a658c24af122740ba35e60b90a4b4 Mon Sep 17 00:00:00 2001 From: Fernando Montoya Date: Mon, 12 Mar 2018 11:40:45 +0100 Subject: [PATCH 120/162] bot: Add Summary and remaining errors to output --- open-bot.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/open-bot.yaml b/open-bot.yaml index b1b713a2c..87b6343ee 100644 --- a/open-bot.yaml +++ b/open-bot.yaml @@ -80,14 +80,28 @@ rules: - "^[\\s\\S]+?\\d+\\s+pending\n+" - "npm ERR!.*\n" - "\n*=============================================================================\n[\\s\\S]*" + string_cleanup: + id: firstError + value: "{{{logResult}}}" + remove: + - "^[\\s\\S]+?(?=\\s2\\)\\s)" + string_cleanup: + id: remainingErrors + value: "{{{logResult}}}" + remove: + - "\\s2\\)\\s[\\s\\S]*" actions: comment: identifier: "ci-result" message: |- @{{commit.author.login}} Please review the following output log for errors: + ```text + {{{firstError}}} + ```
+ Show remaining errors ``` text - {{{logResult}}} + {{{remainingErrors}}} ```
From 7c0c1a089ee3b7ad665f1d0a3105c7b262846b56 Mon Sep 17 00:00:00 2001 From: mc-zone Date: Mon, 12 Mar 2018 21:16:01 +0800 Subject: [PATCH 121/162] Options: default performance to false if not the web/webworker target(#6715) --- lib/WebpackOptionsDefaulter.js | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/WebpackOptionsDefaulter.js b/lib/WebpackOptionsDefaulter.js index e6c9c44d0..0c3fb288d 100644 --- a/lib/WebpackOptionsDefaulter.js +++ b/lib/WebpackOptionsDefaulter.js @@ -13,6 +13,10 @@ const isProductionLikeMode = options => { return options.mode === "production" || !options.mode; }; +const isWebLikeTarget = options => { + return options.target === "web" || options.target === "webworker"; +}; + class WebpackOptionsDefaulter extends OptionsDefaulter { constructor() { super(); @@ -166,25 +170,16 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set("node.__filename", "mock"); this.set("node.__dirname", "mock"); - this.set( - "performance", - "make", - options => (isProductionLikeMode(options) ? false : undefined) - ); - this.set("performance", "call", value => { - if (typeof value === "boolean") { - return value; + this.set("performance", "make", options => { + if (isWebLikeTarget(options) && isProductionLikeMode(options)) { + return {}; } else { - return Object.assign({}, value); + return false; } }); this.set("performance.maxAssetSize", 250000); this.set("performance.maxEntrypointSize", 250000); - this.set( - "performance.hints", - "make", - options => (isProductionLikeMode(options) ? "warning" : false) - ); + this.set("performance.hints", "warning"); this.set("optimization.removeAvailableModules", true); this.set("optimization.removeEmptyChunks", true); From 07571fefddb64b7186b1161d050bf596de339d59 Mon Sep 17 00:00:00 2001 From: mc-zone Date: Tue, 13 Mar 2018 14:21:40 +0800 Subject: [PATCH 122/162] add tests --- .../expected.txt | 6 ++++++ .../index.js | Bin 0 -> 300020 bytes .../webpack.config.js | 10 ++++++++++ 3 files changed, 16 insertions(+) create mode 100644 test/statsCases/performance-oversize-node-target-no-hints/expected.txt create mode 100644 test/statsCases/performance-oversize-node-target-no-hints/index.js create mode 100644 test/statsCases/performance-oversize-node-target-no-hints/webpack.config.js diff --git a/test/statsCases/performance-oversize-node-target-no-hints/expected.txt b/test/statsCases/performance-oversize-node-target-no-hints/expected.txt new file mode 100644 index 000000000..e8c3f73f1 --- /dev/null +++ b/test/statsCases/performance-oversize-node-target-no-hints/expected.txt @@ -0,0 +1,6 @@ +Time: Xms +Built at: Thu Jan 01 1970 00:00:00 GMT + Asset Size Chunks Chunk Names +main.js 296 KiB 0 [emitted] main +Entrypoint main = main.js + [0] ./index.js 293 KiB {0} [built] \ No newline at end of file diff --git a/test/statsCases/performance-oversize-node-target-no-hints/index.js b/test/statsCases/performance-oversize-node-target-no-hints/index.js new file mode 100644 index 0000000000000000000000000000000000000000..6f9f4d4b392a5082d98eda9202d0fcb6df6773ee GIT binary patch literal 300020 zcmeIuOAWvv6aX;JQ$Y}b1KhxEb*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5@S}lp EZ11}Ul>h($ literal 0 HcmV?d00001 diff --git a/test/statsCases/performance-oversize-node-target-no-hints/webpack.config.js b/test/statsCases/performance-oversize-node-target-no-hints/webpack.config.js new file mode 100644 index 000000000..d76807843 --- /dev/null +++ b/test/statsCases/performance-oversize-node-target-no-hints/webpack.config.js @@ -0,0 +1,10 @@ +module.exports = { + mode: "production", + entry: "./index", + target: "node", + stats: { + colors: true, + hash: false, + entrypoints: true + } +}; From 81e47b6eaff4dd23769577b606f16ff90f07e2ef Mon Sep 17 00:00:00 2001 From: rhysd Date: Tue, 13 Mar 2018 17:45:23 +0900 Subject: [PATCH 123/162] Fix typos --- README.md | 6 +++--- examples/chunkhash/README.md | 6 +++--- .../common-chunk-and-vendor-chunk/README.md | 18 +++++++++--------- examples/hybrid-routing/README.md | 6 +++--- examples/multiple-entry-points/README.md | 12 ++++++------ .../HarmonyImportSpecifierDependency.js | 2 +- lib/web/JsonpMainTemplatePlugin.js | 6 +++--- test/cases/parsing/evaluate/index.js | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 79cda6f2d..3b91034a6 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@

webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset. -

+