From 58ba91d78ba631b82d9287075c626596580bb41d Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Tue, 17 Apr 2018 10:37:15 +0200 Subject: [PATCH] fix bug which prevented some chunks to show up in Chunk.getAllAsyncChunks fixes #6931 --- lib/Chunk.js | 12 ++++--- test/ConfigTestCases.test.js | 18 ++++++++-- .../split-chunks/runtime-chunk/a.js | 17 +++++++++ .../split-chunks/runtime-chunk/b.js | 1 + .../split-chunks/runtime-chunk/shared.js | 0 .../split-chunks/runtime-chunk/test.config.js | 5 +++ .../runtime-chunk/webpack.config.js | 24 +++++++++++++ test/helpers/FakeDocument.js | 36 +++++++++++++++++++ 8 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 test/configCases/split-chunks/runtime-chunk/a.js create mode 100644 test/configCases/split-chunks/runtime-chunk/b.js create mode 100644 test/configCases/split-chunks/runtime-chunk/shared.js create mode 100644 test/configCases/split-chunks/runtime-chunk/test.config.js create mode 100644 test/configCases/split-chunks/runtime-chunk/webpack.config.js create mode 100644 test/helpers/FakeDocument.js diff --git a/lib/Chunk.js b/lib/Chunk.js index 6a317a63703..a6335fefd4b 100644 --- a/lib/Chunk.js +++ b/lib/Chunk.js @@ -6,6 +6,7 @@ const util = require("util"); const SortableSet = require("./util/SortableSet"); +const intersect = require("./util/SetHelpers").intersect; const GraphHelpers = require("./GraphHelpers"); let debugId = 1000; const ERR_CHUNK_ENTRY = "Chunk.entry was removed. Use hasRuntime()"; @@ -321,12 +322,15 @@ class Chunk { } getAllAsyncChunks() { - const initialChunks = new Set(); - const queue = new Set(this.groupsIterable); + const queue = new Set(); const chunks = new Set(); - for (const chunkGroup of queue) { - for (const chunk of chunkGroup.chunks) initialChunks.add(chunk); + const initialChunks = intersect( + Array.from(this.groupsIterable, g => new Set(g.chunks)) + ); + + for (const chunkGroup of this.groupsIterable) { + for (const child of chunkGroup.childrenIterable) queue.add(child); } for (const chunkGroup of queue) { diff --git a/test/ConfigTestCases.test.js b/test/ConfigTestCases.test.js index 0ec1e0993aa..5819ac38c2c 100644 --- a/test/ConfigTestCases.test.js +++ b/test/ConfigTestCases.test.js @@ -149,8 +149,18 @@ describe("ConfigTestCases", () => { return test; } + function _beforeEach(title, fn) { + return suite.beforeEach(title, fn); + } + + function _afterEach(title, fn) { + return suite.afterEach(title, fn); + } + const globalContext = { - console: console + console: console, + setTimeout: setTimeout, + clearTimeout: clearTimeout }; function _require(currentDirectory, module) { @@ -175,7 +185,7 @@ describe("ConfigTestCases", () => { options.target === "webworker" ) { fn = vm.runInNewContext( - "(function(require, module, exports, __dirname, __filename, it, window) {" + + "(function(require, module, exports, __dirname, __filename, it, beforeEach, afterEach, window) {" + content + "\n})", globalContext, @@ -183,7 +193,7 @@ describe("ConfigTestCases", () => { ); } else { fn = vm.runInThisContext( - "(function(require, module, exports, __dirname, __filename, it) {" + + "(function(require, module, exports, __dirname, __filename, it, beforeEach, afterEach) {" + content + "\n})", p @@ -200,6 +210,8 @@ describe("ConfigTestCases", () => { path.dirname(p), p, _it, + _beforeEach, + _afterEach, globalContext ); return m.exports; diff --git a/test/configCases/split-chunks/runtime-chunk/a.js b/test/configCases/split-chunks/runtime-chunk/a.js new file mode 100644 index 00000000000..4c87bcac21f --- /dev/null +++ b/test/configCases/split-chunks/runtime-chunk/a.js @@ -0,0 +1,17 @@ +const should = require("should"); +const FakeDocument = require("../../../helpers/FakeDocument"); + +beforeEach(() => { + global.document = new FakeDocument(); +}); + +afterEach(() => { + delete global.document; +}) + +it("should be able to load the split chunk on demand", () => { + const promise = import(/* webpackChunkName: "shared" */ "./shared"); + + const script = document.head._children[0]; + should(script.src).be.eql("dep~b~shared.js"); +}); diff --git a/test/configCases/split-chunks/runtime-chunk/b.js b/test/configCases/split-chunks/runtime-chunk/b.js new file mode 100644 index 00000000000..d44247b1607 --- /dev/null +++ b/test/configCases/split-chunks/runtime-chunk/b.js @@ -0,0 +1 @@ +import "./shared"; diff --git a/test/configCases/split-chunks/runtime-chunk/shared.js b/test/configCases/split-chunks/runtime-chunk/shared.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/configCases/split-chunks/runtime-chunk/test.config.js b/test/configCases/split-chunks/runtime-chunk/test.config.js new file mode 100644 index 00000000000..dad54da8f4a --- /dev/null +++ b/test/configCases/split-chunks/runtime-chunk/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function(i, options) { + return ["runtime.js", "a.js"]; + } +}; diff --git a/test/configCases/split-chunks/runtime-chunk/webpack.config.js b/test/configCases/split-chunks/runtime-chunk/webpack.config.js new file mode 100644 index 00000000000..1958da90461 --- /dev/null +++ b/test/configCases/split-chunks/runtime-chunk/webpack.config.js @@ -0,0 +1,24 @@ +const path = require("path"); + +module.exports = { + entry: { + a: "./a", + b: "./b" + }, + target: "web", + output: { + filename: "[name].js" + }, + optimization: { + runtimeChunk: "single", + splitChunks: { + cacheGroups: { + dep: { + chunks: "all", + test: path.resolve(__dirname, "shared.js"), + enforce: true + } + } + } + } +}; diff --git a/test/helpers/FakeDocument.js b/test/helpers/FakeDocument.js new file mode 100644 index 00000000000..0c9d80de06f --- /dev/null +++ b/test/helpers/FakeDocument.js @@ -0,0 +1,36 @@ +module.exports = class FakeDocument { + constructor() { + this.head = this.createElement("head"); + } + + createElement(type) { + return new FakeElement(type); + } + + getElementsByTagName(name) { + if (name === "head") return [this.head]; + throw new Error( + `FakeDocument.getElementsByTagName(${name}): not implemented` + ); + } +}; + +class FakeElement { + constructor(type) { + this._type = type; + this._children = []; + this._attributes = Object.create(null); + } + + appendChild(node) { + this._children.push(node); + } + + setAttribute(name, value) { + this._attributes[name] = value; + } + + getAttribute(name) { + return this._attributes[name]; + } +}