Skip to content

Commit 0ea37a5

Browse files
committed
Disallow Scope Hoisting when using HMR
fixes webpack#5504
1 parent 287d587 commit 0ea37a5

File tree

7 files changed

+78
-29
lines changed

7 files changed

+78
-29
lines changed

lib/optimize/ModuleConcatenationPlugin.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"use strict";
66

77
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
8+
const ModuleHotAcceptDependency = require("../dependencies/ModuleHotAcceptDependency");
9+
const ModuleHotDeclineDependency = require("../dependencies/ModuleHotDeclineDependency");
810
const ConcatenatedModule = require("./ConcatenatedModule");
911
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
1012
const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
@@ -67,6 +69,12 @@ class ModuleConcatenationPlugin {
6769
continue;
6870
}
6971

72+
// Hot Module Replacement need it's own module to work correctly
73+
if(module.dependencies.some(dep => dep instanceof ModuleHotAcceptDependency || dep instanceof ModuleHotDeclineDependency)) {
74+
setBailoutReason(module, "Module uses Hot Module Replacement");
75+
continue;
76+
}
77+
7078
relevantModules.push(module);
7179

7280
// Module must not be the entry points

test/HotTestCases.test.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,38 @@ describe("HotTestCases", () => {
3737
updateIndex: 0
3838
}
3939
};
40-
const options = {
41-
context: testDirectory,
42-
entry: "./index.js",
43-
output: {
44-
path: outputDirectory,
45-
filename: "bundle.js"
46-
},
47-
module: {
48-
loaders: [{
49-
test: /\.js$/,
50-
loader: path.join(__dirname, "hotCases", "fake-update-loader.js"),
51-
enforce: "pre"
52-
}, {
53-
test: /\.css$/,
54-
use: ExtractTextPlugin.extract({
55-
fallback: "style-loader",
56-
use: "css-loader"
57-
})
58-
}]
59-
},
60-
target: "async-node",
61-
plugins: [
62-
new webpack.HotModuleReplacementPlugin(),
63-
new webpack.NamedModulesPlugin(),
64-
new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions),
65-
new ExtractTextPlugin("bundle.css")
66-
],
67-
recordsPath: recordsPath
68-
};
40+
const configPath = path.join(testDirectory, "webpack.config.js");
41+
let options = {};
42+
if(fs.existsSync(configPath))
43+
options = require(configPath);
44+
if(!options.context) options.context = testDirectory;
45+
if(!options.entry) options.entry = "./index.js";
46+
if(!options.output) options.output = {};
47+
if(!options.output.path) options.output.path = outputDirectory;
48+
if(!options.output.filename) options.output.filename = "bundle.js";
49+
if(options.output.pathinfo === undefined) options.output.pathinfo = true;
50+
if(!options.module) options.module = {};
51+
if(!options.module.rules) options.module.rules = [];
52+
options.module.rules.push({
53+
test: /\.js$/,
54+
loader: path.join(__dirname, "hotCases", "fake-update-loader.js"),
55+
enforce: "pre"
56+
}, {
57+
test: /\.css$/,
58+
use: ExtractTextPlugin.extract({
59+
fallback: "style-loader",
60+
use: "css-loader"
61+
})
62+
});
63+
if(!options.target) options.target = "async-node";
64+
if(!options.plugins) options.plugins = [];
65+
options.plugins.push(
66+
new webpack.HotModuleReplacementPlugin(),
67+
new webpack.NamedModulesPlugin(),
68+
new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions),
69+
new ExtractTextPlugin("bundle.css")
70+
);
71+
if(!options.recordsPath) options.recordsPath = recordsPath;
6972
const compiler = webpack(options);
7073
compiler.run((err, stats) => {
7174
if(err) return done(err);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default 1;
2+
---
3+
export default 2;
4+
---
5+
export default 2;
6+
---
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default 10;
2+
---
3+
export default 10;
4+
---
5+
export default 20;
6+
---
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import "./module";
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import value1 from "./a";
2+
import value2 from "./b";
3+
4+
it("should allow to hot replace modules in a ConcatenatedModule", function(done) {
5+
value1.should.be.eql(1);
6+
value2.should.be.eql(10);
7+
module.hot.accept("./a", function() {
8+
value1.should.be.eql(2);
9+
NEXT(require("../../update")(done));
10+
});
11+
module.hot.accept("./b", function() {
12+
value2.should.be.eql(20);
13+
done();
14+
});
15+
NEXT(require("../../update")(done));
16+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use strict";
2+
3+
const webpack = require("../../../../");
4+
5+
module.exports = {
6+
plugins: [
7+
new webpack.optimize.ModuleConcatenationPlugin()
8+
]
9+
};

0 commit comments

Comments
 (0)