diff --git a/lib/Chunk.js b/lib/Chunk.js index b47d84677..9e5dc50c6 100644 --- a/lib/Chunk.js +++ b/lib/Chunk.js @@ -342,14 +342,14 @@ Chunk.prototype.checkConstraints = function() { var chunk = this; chunk.chunks.forEach(function(child, idx) { if(chunk.chunks.indexOf(child) !== idx) - console.log("checkConstraints: duplicate child in chunk", chunk.debugId, child.debugId); + throw new Error("checkConstraints: duplicate child in chunk " + chunk.debugId + " " + child.debugId); if(child.parents.indexOf(chunk) < 0) - console.log("checkConstraints: child missing parent", chunk.debugId, "->", child.debugId); + throw new Error("checkConstraints: child missing parent " + chunk.debugId + " -> " + child.debugId); }); chunk.parents.forEach(function(parent, idx) { if(chunk.parents.indexOf(parent) !== idx) - console.log("checkConstraints: duplicate parent in chunk", chunk.debugId, parent.debugId); + throw new Error("checkConstraints: duplicate parent in chunk " + chunk.debugId + " " + parent.debugId); if(parent.chunks.indexOf(chunk) < 0) - console.log("checkConstraints: parent missing child", parent.debugId, "<-", chunk.debugId); + throw new Error("checkConstraints: parent missing child " + parent.debugId + " <- " + chunk.debugId); }); }; diff --git a/lib/Compilation.js b/lib/Compilation.js index 69f4e22d2..2cab1873c 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -46,10 +46,8 @@ function Compilation(compiler) { this._modules = {}; this.cache = null; this.records = null; - this.nextFreeModuleId = 0; - this.nextFreeChunkId = 0; - this.nextFreeModuleIndex = 0; - this.nextFreeModuleIndex2 = 0; + this.nextFreeModuleIndex = undefined; + this.nextFreeModuleIndex2 = undefined; this.additionalChunkAssets = []; this.assets = {}; this.errors = []; @@ -492,10 +490,6 @@ Compilation.prototype.unseal = function unseal() { this.applyPlugins("unseal"); this.chunks.length = 0; this.namedChunks = {}; - this.nextFreeChunkId = this.nextFreeChunkIdBeforeSeal; - this.nextFreeModuleId = this.nextFreeModuleIdBeforeSeal; - this.nextFreeModuleIndex = this.nextFreeModuleIndexBeforeSeal; - this.nextFreeModuleIndex2 = this.nextFreeModuleIndex2BeforeSeal; this.additionalChunkAssets.length = 0; this.assets = {}; this.modules.forEach(function(module) { @@ -510,10 +504,8 @@ Compilation.prototype.seal = function seal(callback) { if(a.name > b.name) return 1; return 0; }); - this.nextFreeChunkIdBeforeSeal = this.nextFreeChunkId; - this.nextFreeModuleIdBeforeSeal = this.nextFreeModuleId; - this.nextFreeModuleIndexBeforeSeal = this.nextFreeModuleIndex; - this.nextFreeModuleIndex2BeforeSeal = this.nextFreeModuleIndex2; + this.nextFreeModuleIndex = 0; + this.nextFreeModuleIndex2 = 0; this.preparedChunks.forEach(function(preparedChunk) { var module = preparedChunk.module; var chunk = this.addChunk(preparedChunk.name, module); @@ -737,17 +729,59 @@ Compilation.prototype.removeChunkFromDependencies = function removeChunkFromDepe }; Compilation.prototype.applyModuleIds = function applyModuleIds() { + var unusedIds = []; + var nextFreeModuleId = 0; + if(this.usedModuleIds) { + var usedIds = Object.keys(this.usedModuleIds).map(function(key) { + return this.usedModuleIds[key]; + }, this).sort(); + var usedNumberIds = usedIds.filter(function(id) { + return typeof id === "number"; + }); + nextFreeModuleId = usedNumberIds.reduce(function(a, b) { + return Math.max(a, b); + }, -1) + 1; + for(var i = 0; i < nextFreeModuleId; i++) { + if(this.usedModuleIds[i] !== i) + unusedIds.push(i); + } + unusedIds.reverse(); + } this.modules.forEach(function(module) { if(module.id === null) { - module.id = this.nextFreeModuleId++; + if(unusedIds.length > 0) + module.id = unusedIds.pop(); + else + module.id = nextFreeModuleId++; } }, this); }; Compilation.prototype.applyChunkIds = function applyChunkIds() { + var unusedIds = []; + var nextFreeChunkId = 0; + if(this.usedChunkIds) { + var usedIds = Object.keys(this.usedChunkIds).map(function(key) { + return this.usedChunkIds[key]; + }, this).sort(); + var usedNumberIds = usedIds.filter(function(id) { + return typeof id === "number"; + }); + nextFreeChunkId = usedNumberIds.reduce(function(a, b) { + return Math.max(a, b); + }, -1) + 1; + for(var i = 0; i < nextFreeChunkId; i++) { + if(this.usedChunkIds[i] !== i) + unusedIds.push(i); + } + unusedIds.reverse(); + } this.chunks.forEach(function(chunk) { if(chunk.id === null) { - chunk.id = this.nextFreeChunkId++; + if(unusedIds.length > 0) + chunk.id = unusedIds.pop(); + else + chunk.id = nextFreeChunkId++; } if(!chunk.ids) { chunk.ids = [chunk.id]; @@ -950,9 +984,14 @@ Compilation.prototype.createChildCompiler = function(name, outputOptions) { }; Compilation.prototype.checkConstraints = function() { + var usedIds = {}; + this.modules.forEach(function(module) { + if(usedIds[module.id]) + throw new Error("checkConstraints: duplicate module id " + module.id); + }); this.chunks.forEach(function(chunk, idx) { if(this.chunks.indexOf(chunk) !== idx) - console.log("checkConstraints: duplicate chunk in compilation", chunk.debugId); + throw new Error("checkConstraints: duplicate chunk in compilation " + chunk.debugId); chunk.checkConstraints(); }.bind(this)); }; diff --git a/lib/HotModuleReplacement.runtime.js b/lib/HotModuleReplacement.runtime.js index 5a15f921b..9c3ac34a2 100644 --- a/lib/HotModuleReplacement.runtime.js +++ b/lib/HotModuleReplacement.runtime.js @@ -92,9 +92,9 @@ module.exports = function() { hot._selfAccepted = dep; else if(typeof dep === "object") for(var i = 0; i < dep.length; i++) - hot._acceptedDependencies[dep[i]] = callback; + hot._acceptedDependencies[dep[i]] = callback || function() {}; else - hot._acceptedDependencies[dep] = callback; + hot._acceptedDependencies[dep] = callback || function() {}; }, decline: function(dep) { if(typeof dep === "undefined") @@ -174,10 +174,8 @@ module.exports = function() { } hotRequestedFilesMap = {}; - hotAvailableFilesMap = {}; hotWaitingFilesMap = {}; - for(var i = 0; i < update.c.length; i++) - hotAvailableFilesMap[update.c[i]] = true; + hotAvailableFilesMap = update.c; hotUpdateNewHash = update.h; hotSetStatus("prepare"); @@ -339,9 +337,18 @@ module.exports = function() { for(var id in hotUpdate) { if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { moduleId = toModuleId(id); - var result = getAffectedStuff(moduleId); + var result; + if(hotUpdate[id]) { + result = getAffectedStuff(moduleId); + } else { + result = { + type: "disposed", + moduleId: id + }; + } var abortError = false; var doApply = false; + var doDispose = false; var chainInfo = ""; if(result.chain) { chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); @@ -370,6 +377,11 @@ module.exports = function() { options.onAccepted(result); doApply = true; break; + case "disposed": + if(options.onDisposed) + options.onDisposed(result); + doDispose = true; + break; default: throw new Error("Unexception type " + result.type); } @@ -388,6 +400,12 @@ module.exports = function() { } } } + if(doDispose) { + addAllToSet(outdatedModules, [result.moduleId]); + appliedUpdate[moduleId] = function() { + console.warn("[HMR] unexpected require(" + result.moduleId + ") to disposed module"); + }; + } } } @@ -404,6 +422,12 @@ module.exports = function() { // Now in "dispose" phase hotSetStatus("dispose"); + Object.keys(hotAvailableFilesMap).forEach(function(chunkId) { + if(hotAvailableFilesMap[chunkId] === false) { + hotDisposeChunk(chunkId); + } + }); + var idx; var queue = outdatedModules.slice(); while(queue.length > 0) { diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index 0245f68cb..54d3e07f1 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -105,7 +105,7 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) { }); var hotUpdateMainContent = { h: this.hash, - c: [] + c: {} }; Object.keys(records.chunkHashs).forEach(function(chunkId) { chunkId = +chunkId; @@ -116,18 +116,27 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) { var newModules = currentChunk.modules.filter(function(module) { return module.hotUpdate; }); - if(newModules.length > 0) { - var source = hotUpdateChunkTemplate.render(chunkId, newModules, this.hash, this.moduleTemplate, this.dependencyTemplates); + var allModules = {}; + currentChunk.modules.forEach(function(module) { + allModules[module.id] = true; + }); + var removedModules = records.chunkModuleIds[chunkId].filter(function(id) { + return !allModules[id]; + }); + if(newModules.length > 0 || removedModules.length > 0) { + var source = hotUpdateChunkTemplate.render(chunkId, newModules, removedModules, this.hash, this.moduleTemplate, this.dependencyTemplates); var filename = this.getPath(hotUpdateChunkFilename, { hash: records.hash, chunk: currentChunk }); this.additionalChunkAssets.push(filename); this.assets[filename] = source; - hotUpdateMainContent.c.push(chunkId); + hotUpdateMainContent.c[chunkId] = true; currentChunk.files.push(filename); this.applyPlugins("chunk-asset", currentChunk, filename); } + } else { + hotUpdateMainContent.c[chunkId] = false; } }, this); var source = new RawSource(JSON.stringify(hotUpdateMainContent)); diff --git a/lib/HotUpdateChunkTemplate.js b/lib/HotUpdateChunkTemplate.js index 0175cf574..5b5fbbbd5 100644 --- a/lib/HotUpdateChunkTemplate.js +++ b/lib/HotUpdateChunkTemplate.js @@ -13,13 +13,14 @@ module.exports = HotUpdateChunkTemplate; HotUpdateChunkTemplate.prototype = Object.create(Template.prototype); HotUpdateChunkTemplate.prototype.constructor = HotUpdateChunkTemplate; -HotUpdateChunkTemplate.prototype.render = function(id, modules, hash, moduleTemplate, dependencyTemplates) { +HotUpdateChunkTemplate.prototype.render = function(id, modules, removedModules, hash, moduleTemplate, dependencyTemplates) { var modulesSource = this.renderChunkModules({ id: id, - modules: modules + modules: modules, + removedModules: removedModules }, moduleTemplate, dependencyTemplates); - var core = this.applyPluginsWaterfall("modules", modulesSource, modules, moduleTemplate, dependencyTemplates); - var source = this.applyPluginsWaterfall("render", core, modules, hash, id, moduleTemplate, dependencyTemplates); + var core = this.applyPluginsWaterfall("modules", modulesSource, modules, removedModules, moduleTemplate, dependencyTemplates); + var source = this.applyPluginsWaterfall("render", core, modules, removedModules, hash, id, moduleTemplate, dependencyTemplates); return source; }; diff --git a/lib/JsonpHotUpdateChunkTemplatePlugin.js b/lib/JsonpHotUpdateChunkTemplatePlugin.js index 35f696dce..09a01f1ff 100644 --- a/lib/JsonpHotUpdateChunkTemplatePlugin.js +++ b/lib/JsonpHotUpdateChunkTemplatePlugin.js @@ -9,7 +9,7 @@ function JsonpHotUpdateChunkTemplatePlugin() {} module.exports = JsonpHotUpdateChunkTemplatePlugin; JsonpHotUpdateChunkTemplatePlugin.prototype.apply = function(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, hash, id) { + hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) { var jsonpFunction = this.outputOptions.hotUpdateFunction; var source = new ConcatSource(); source.add(jsonpFunction + "(" + JSON.stringify(id) + ","); diff --git a/lib/JsonpMainTemplatePlugin.js b/lib/JsonpMainTemplatePlugin.js index c163d337a..34c88974e 100644 --- a/lib/JsonpMainTemplatePlugin.js +++ b/lib/JsonpMainTemplatePlugin.js @@ -181,6 +181,9 @@ JsonpMainTemplatePlugin.prototype.apply = function(mainTemplate) { }); return source + "\n" + + "function hotDisposeChunk(chunkId) {\n" + + "\tdelete installedChunks[chunkId];\n" + + "}\n" + "var parentHotUpdateCallback = this[" + JSON.stringify(hotUpdateFunction) + "];\n" + "this[" + JSON.stringify(hotUpdateFunction) + "] = " + Template.getFunctionContent(require("./JsonpMainTemplate.runtime.js")) .replace(/\/\/\$semicolon/g, ";") diff --git a/lib/RecordIdsPlugin.js b/lib/RecordIdsPlugin.js index 2b01b046e..655c990a6 100644 --- a/lib/RecordIdsPlugin.js +++ b/lib/RecordIdsPlugin.js @@ -19,28 +19,30 @@ function makeRelative(compiler, identifier) { RecordIdsPlugin.prototype.apply = function(compiler) { compiler.plugin("compilation", function(compilation) { compilation.plugin("record-modules", function(modules, records) { - records.nextFreeModuleId = compilation.nextFreeModuleId; if(!records.modules) records.modules = {}; if(!records.modules.byIdentifier) records.modules.byIdentifier = {}; + if(!records.modules.usedIds) records.modules.usedIds = {}; modules.forEach(function(module) { var identifier = makeRelative(compiler, module.identifier()); records.modules.byIdentifier[identifier] = module.id; + records.modules.usedIds[module.id] = module.id; }); }); compilation.plugin("revive-modules", function(modules, records) { - if(typeof records.nextFreeModuleId === "number") - compilation.nextFreeModuleId = records.nextFreeModuleId; - if(!records.modules || !records.modules.byIdentifier) return; - var usedIds = {}; - modules.forEach(function(module) { - if(module.id !== null) return; - var identifier = makeRelative(compiler, module.identifier()); - var id = records.modules.byIdentifier[identifier]; - if(id === undefined) return; - if(usedIds[id]) return; - usedIds[id] = true; - module.id = id; - }); + if(!records.modules) return; + if(records.modules.byIdentifier) { + var usedIds = {}; + modules.forEach(function(module) { + if(module.id !== null) return; + var identifier = makeRelative(compiler, module.identifier()); + var id = records.modules.byIdentifier[identifier]; + if(id === undefined) return; + if(usedIds[id]) return; + usedIds[id] = true; + module.id = id; + }); + } + compilation.usedModuleIds = records.modules.usedIds; }); function getDepBlockIdent(chunk, block) { @@ -63,6 +65,7 @@ RecordIdsPlugin.prototype.apply = function(compiler) { if(!records.chunks) records.chunks = {}; if(!records.chunks.byName) records.chunks.byName = {}; if(!records.chunks.byBlocks) records.chunks.byBlocks = {}; + records.chunks.usedIds = {}; chunks.forEach(function(chunk) { var name = chunk.name; var blockIdents = chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean); @@ -70,11 +73,10 @@ RecordIdsPlugin.prototype.apply = function(compiler) { blockIdents.forEach(function(blockIdent) { records.chunks.byBlocks[blockIdent] = chunk.id; }); + records.chunks.usedIds[chunk.id] = chunk.id; }); }); compilation.plugin("revive-chunks", function(chunks, records) { - if(typeof records.nextFreeChunkId === "number") - compilation.nextFreeChunkId = records.nextFreeChunkId; if(!records.chunks) return; var usedIds = {}; if(records.chunks.byName) { @@ -123,6 +125,7 @@ RecordIdsPlugin.prototype.apply = function(compiler) { chunk.id = id; }); } + compilation.usedChunkIds = records.chunks.usedIds; }); }); }; diff --git a/lib/Template.js b/lib/Template.js index b72aac7da..0940077eb 100644 --- a/lib/Template.js +++ b/lib/Template.js @@ -97,7 +97,23 @@ Template.prototype.renderChunkModules = function(chunk, moduleTemplate, dependen source.add("[]"); return source; } + var removedModules = chunk.removedModules; + var allModules = chunk.modules.map(function(module) { + return { + id: module.id, + source: moduleTemplate.render(module, dependencyTemplates, chunk) + }; + }); + if(removedModules && removedModules.length > 0) { + removedModules.forEach(function(id) { + allModules.push({ + id: id, + source: "false" + }); + }); + } var bounds = this.getModulesArrayBounds(chunk.modules); + if(bounds) { // Render a spare array var minId = bounds[0]; @@ -105,7 +121,7 @@ Template.prototype.renderChunkModules = function(chunk, moduleTemplate, dependen if(minId !== 0) source.add("Array(" + minId + ").concat("); source.add("[\n"); var modules = {}; - chunk.modules.forEach(function(module) { + allModules.forEach(function(module) { modules[module.id] = module; }); for(var idx = minId; idx <= maxId; idx++) { @@ -114,7 +130,7 @@ Template.prototype.renderChunkModules = function(chunk, moduleTemplate, dependen source.add("/* " + idx + " */"); if(module) { source.add("\n"); - source.add(moduleTemplate.render(module, dependencyTemplates, chunk)); + source.add(module.source); } } source.add("\n" + prefix + "]"); @@ -122,7 +138,7 @@ Template.prototype.renderChunkModules = function(chunk, moduleTemplate, dependen } else { // Render an object source.add("{\n"); - chunk.modules.slice().sort(function(a, b) { + allModules.sort(function(a, b) { var aId = a.id + ""; var bId = b.id + ""; if(aId < bId) return -1; @@ -131,7 +147,7 @@ Template.prototype.renderChunkModules = function(chunk, moduleTemplate, dependen }).forEach(function(module, idx) { if(idx !== 0) source.add(",\n"); source.add("\n/***/ " + JSON.stringify(module.id) + ":\n"); - source.add(moduleTemplate.render(module, dependencyTemplates, chunk)); + source.add(module.source); }); source.add("\n\n" + prefix + "}"); } diff --git a/lib/node/NodeHotUpdateChunkTemplatePlugin.js b/lib/node/NodeHotUpdateChunkTemplatePlugin.js index aec6a7b6b..124b21e33 100644 --- a/lib/node/NodeHotUpdateChunkTemplatePlugin.js +++ b/lib/node/NodeHotUpdateChunkTemplatePlugin.js @@ -8,7 +8,7 @@ function NodeHotUpdateChunkTemplatePlugin() {} module.exports = NodeHotUpdateChunkTemplatePlugin; NodeHotUpdateChunkTemplatePlugin.prototype.apply = function(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, hash, id) { + hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) { var source = new ConcatSource(); source.add("exports.id = " + JSON.stringify(id) + ";\nexports.modules = "); source.add(modulesSource); diff --git a/lib/node/NodeMainTemplate.runtime.js b/lib/node/NodeMainTemplate.runtime.js index b67202e46..39850ecd8 100644 --- a/lib/node/NodeMainTemplate.runtime.js +++ b/lib/node/NodeMainTemplate.runtime.js @@ -17,4 +17,8 @@ module.exports = function() { } return Promise.resolve(update); } + + function hotDiposeChunk(chunkId) { + delete installedChunks[chunkId]; + } }; diff --git a/lib/node/NodeMainTemplateAsync.runtime.js b/lib/node/NodeMainTemplateAsync.runtime.js index 1e44b9d66..f2741fc79 100644 --- a/lib/node/NodeMainTemplateAsync.runtime.js +++ b/lib/node/NodeMainTemplateAsync.runtime.js @@ -33,4 +33,8 @@ module.exports = function() { }); }); } + + function hotDiposeChunk(chunkId) { + delete installedChunks[chunkId]; + } }; diff --git a/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js b/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js index f3113b427..ce24ca957 100644 --- a/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +++ b/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js @@ -9,7 +9,7 @@ function WebWorkerHotUpdateChunkTemplatePlugin() {} module.exports = WebWorkerHotUpdateChunkTemplatePlugin; WebWorkerHotUpdateChunkTemplatePlugin.prototype.apply = function(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, hash, id) { + hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) { var chunkCallbackName = this.outputOptions.hotUpdateFunction || Template.toIdentifier("webpackHotUpdate" + (this.outputOptions.library || "")); var source = new ConcatSource(); source.add(chunkCallbackName + "(" + JSON.stringify(id) + ","); diff --git a/lib/webworker/WebWorkerMainTemplate.runtime.js b/lib/webworker/WebWorkerMainTemplate.runtime.js index d81315252..6c70b8ed5 100644 --- a/lib/webworker/WebWorkerMainTemplate.runtime.js +++ b/lib/webworker/WebWorkerMainTemplate.runtime.js @@ -48,4 +48,8 @@ module.exports = function() { } }; } + + function hotDiposeChunk(chunkId) { + delete installedChunks[chunkId]; + } }; diff --git a/test/TestCases.test.js b/test/TestCases.test.js index 0bf747b44..41c401594 100644 --- a/test/TestCases.test.js +++ b/test/TestCases.test.js @@ -159,7 +159,16 @@ describe("TestCases", function() { }] }, plugins: (config.plugins || []).concat( - new webpack.dependencies.LabeledModulesPlugin() + new webpack.dependencies.LabeledModulesPlugin(), + function() { + this.plugin("compilation", function(compilation) { + ["optimize", "optimize-modules-basic", "optimize-chunks-basic", "after-optimize-tree", "after-optimize-assets"].forEach(function(hook) { + compilation.plugin(hook, function() { + compilation.checkConstraints(); + }); + }); + }); + } ) }; webpack(options, function(err, stats) { diff --git a/test/hotCases/runtime/dispose-removed-chunk/a.js b/test/hotCases/runtime/dispose-removed-chunk/a.js new file mode 100644 index 000000000..ff9f2cdc4 --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-chunk/a.js @@ -0,0 +1 @@ +export default Date.now(); \ No newline at end of file diff --git a/test/hotCases/runtime/dispose-removed-chunk/b.js b/test/hotCases/runtime/dispose-removed-chunk/b.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/hotCases/runtime/dispose-removed-chunk/index.js b/test/hotCases/runtime/dispose-removed-chunk/index.js new file mode 100644 index 000000000..2db0ff824 --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-chunk/index.js @@ -0,0 +1,17 @@ +it("should dispose a chunk which is removed from bundle", function(done) { + var m1 = require("./module"); + NEXT(require("../../update")(done, true, function() { + var m2 = require("./module"); + NEXT(require("../../update")(done, true, function() { + var m3 = require("./module"); + Promise.all([m1.default, m2.default, m3.default]).then(function(arr) { + arr[0].should.be.not.eql(arr[2]); + done(); + }); + })); + })); +}); + +if(module.hot) { + module.hot.accept("./module"); +} diff --git a/test/hotCases/runtime/dispose-removed-chunk/module.js b/test/hotCases/runtime/dispose-removed-chunk/module.js new file mode 100644 index 000000000..9bbd615a3 --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-chunk/module.js @@ -0,0 +1,5 @@ +export default System.import("./a"); +--- +export default System.import("./b"); +--- +export default System.import("./a"); diff --git a/test/hotCases/runtime/dispose-removed-module/a.js b/test/hotCases/runtime/dispose-removed-module/a.js new file mode 100644 index 000000000..ce315e6cd --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-module/a.js @@ -0,0 +1,13 @@ +var callback; +export default function setHandler(cb) { + callback = cb; +}; + +if(module.hot) { + module.hot.dispose(function() { + callback(module.id); + }); +} +--- +--- +export default module.id; \ No newline at end of file diff --git a/test/hotCases/runtime/dispose-removed-module/b.js b/test/hotCases/runtime/dispose-removed-module/b.js new file mode 100644 index 000000000..e152b57dd --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-module/b.js @@ -0,0 +1 @@ +export default 1; \ No newline at end of file diff --git a/test/hotCases/runtime/dispose-removed-module/index.js b/test/hotCases/runtime/dispose-removed-module/index.js new file mode 100644 index 000000000..bd3da8723 --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-module/index.js @@ -0,0 +1,20 @@ +var m = require("./module"); + +it("should dispose a module which is removed from bundle", function(done) { + var disposed = []; + m.setHandler(function(id) { + disposed.push(id); + }); + NEXT(require("../../update")(done, true, function() { + require("./module"); + NEXT(require("../../update")(done, true, function() { + var newModule = require("./module"); + disposed.should.be.eql([newModule.default]); + done(); + })); + })); +}); + +if(module.hot) { + module.hot.accept("./module"); +} diff --git a/test/hotCases/runtime/dispose-removed-module/module.js b/test/hotCases/runtime/dispose-removed-module/module.js new file mode 100644 index 000000000..84354b2c2 --- /dev/null +++ b/test/hotCases/runtime/dispose-removed-module/module.js @@ -0,0 +1,5 @@ +export { default as setHandler } from "./a"; +--- +import "./b" +--- +export { default as default } from "./a"; \ No newline at end of file diff --git a/test/statsCases/aggressive-splitting-entry/input-records.json b/test/statsCases/aggressive-splitting-entry/input-records.json index 40577dbd7..72b64a7f8 100644 --- a/test/statsCases/aggressive-splitting-entry/input-records.json +++ b/test/statsCases/aggressive-splitting-entry/input-records.json @@ -1,5 +1,4 @@ { - "nextFreeModuleId": 5, "modules": { "byIdentifier": { "b.js": 0, @@ -7,12 +6,22 @@ "d.js": 2, "e.js": 3, "index.js": 4 + }, + "usedIds": { + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4 } }, - "nextFreeChunkId": 2, "chunks": { "byName": {}, - "byBlocks": {} + "byBlocks": {}, + "usedIds": { + "0": 0, + "1": 1 + } }, "aggressiveSplits": [ { diff --git a/test/statsCases/aggressive-splitting-entry/records.json b/test/statsCases/aggressive-splitting-entry/records.json deleted file mode 100644 index 795d2ec69..000000000 --- a/test/statsCases/aggressive-splitting-entry/records.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "nextFreeModuleId": 8, - "modules": { - "byIdentifier": { - "b.js": 0, - "c.js": 1, - "d.js": 2, - "e.js": 3, - "index.js": 4, - "a.js": 5, - "f.js": 6, - "g.js": 7 - } - }, - "nextFreeChunkId": 5, - "chunks": { - "byName": {}, - "byBlocks": {} - }, - "aggressiveSplits": [ - { - "modules": [ - "b.js", - "c.js" - ], - "hash": "48c8b1dae03a37363ec82be4f7b781bc", - "id": 1 - }, - { - "modules": [ - "a.js", - "d.js" - ], - "hash": "a5b577236621262c2bcf4c70b743a3bf", - "id": 3 - } - ] -} \ No newline at end of file diff --git a/test/statsCases/aggressive-splitting-entry/webpack.config.js b/test/statsCases/aggressive-splitting-entry/webpack.config.js index 1f8169d12..e02cb8809 100644 --- a/test/statsCases/aggressive-splitting-entry/webpack.config.js +++ b/test/statsCases/aggressive-splitting-entry/webpack.config.js @@ -14,7 +14,7 @@ module.exports = { }) ], recordsInputPath: __dirname + "/input-records.json", - recordsOutputPath: __dirname + "/records.json", + //recordsOutputPath: __dirname + "/records.json", stats: { reasons: false, chunkModules: true, diff --git a/test/statsCases/aggressive-splitting-on-demand/input-records.json b/test/statsCases/aggressive-splitting-on-demand/input-records.json index 6b8df9a3f..712433093 100644 --- a/test/statsCases/aggressive-splitting-on-demand/input-records.json +++ b/test/statsCases/aggressive-splitting-on-demand/input-records.json @@ -1,5 +1,4 @@ { - "nextFreeModuleId": 12, "modules": { "byIdentifier": { "a.js": 0, @@ -14,9 +13,22 @@ "index.js": 9, "j.js": 10, "k.js": 11 + }, + "usedIds": { + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "8": 8, + "9": 9, + "10": 10, + "11": 11 } }, - "nextFreeChunkId": 9, "chunks": { "byName": { "main": 6 @@ -32,6 +44,17 @@ "index.js:4/4:0": 5, "index.js:2/4:0": 7, "index.js:0/4": 8 + }, + "usedIds": { + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "8": 8 } }, "aggressiveSplits": [ diff --git a/test/statsCases/aggressive-splitting-on-demand/records.json b/test/statsCases/aggressive-splitting-on-demand/records.json deleted file mode 100644 index 6111fc064..000000000 --- a/test/statsCases/aggressive-splitting-on-demand/records.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "nextFreeModuleId": 12, - "modules": { - "byIdentifier": { - "a.js": 0, - "b.js": 1, - "c.js": 2, - "d.js": 3, - "e.js": 4, - "f.js": 5, - "g.js": 6, - "h.js": 7, - "i.js": 8, - "index.js": 9, - "j.js": 10, - "k.js": 11 - } - }, - "nextFreeChunkId": 12, - "chunks": { - "byName": { - "main": 6 - }, - "byBlocks": { - "index.js:4/4:2": 0, - "index.js:3/4:0": 0, - "index.js:2/4:1": 1, - "index.js:4/4:1": 1, - "index.js:3/4:2": 2, - "index.js:3/4:1": 3, - "index.js:1/4": 4, - "index.js:4/4:0": 5, - "index.js:2/4:0": 7, - "index.js:0/4": 8, - "index.js:3/5:0": 0, - "index.js:4/5:2": 0, - "index.js:5/5:2": 0, - "index.js:2/5:1": 1, - "index.js:4/5:1": 1, - "index.js:5/5:1": 1, - "index.js:3/5:2": 2, - "index.js:5/5:4": 2, - "index.js:3/5:1": 3, - "index.js:5/5:3": 3, - "index.js:1/5": 4, - "index.js:4/5:0": 9, - "index.js:5/5:0": 9, - "index.js:2/5:0": 4, - "index.js:0/5": 11, - "index.js:1/5:1": 4, - "index.js:1/5:0": 9 - } - }, - "aggressiveSplits": [ - { - "modules": [ - "d.js", - "e.js" - ], - "hash": "11324f155de813ceb6584bbb3820bce4", - "id": 1 - }, - { - "modules": [ - "h.js", - "i.js" - ], - "hash": "e91ec4902ca3057b42bb3d87c855733c", - "id": 3 - }, - { - "modules": [ - "b.js", - "c.js" - ], - "hash": "0947f0875d56ab0bfe02f1ea31783ed8", - "id": 4 - }, - { - "modules": [ - "a.js", - "b.js" - ], - "hash": "2a1056b05b68590f7fad418ec0619c8d", - "id": 5 - }, - { - "modules": [ - "f.js", - "g.js" - ], - "hash": "7434ce273df5c166f742c631347b7aec", - "id": 0 - }, - { - "modules": [ - "j.js", - "k.js" - ], - "hash": "5ae9e18455b866684bd0e85f8c7a8181", - "id": 2 - } - ] -} \ No newline at end of file diff --git a/test/statsCases/aggressive-splitting-on-demand/webpack.config.js b/test/statsCases/aggressive-splitting-on-demand/webpack.config.js index 1f8169d12..e02cb8809 100644 --- a/test/statsCases/aggressive-splitting-on-demand/webpack.config.js +++ b/test/statsCases/aggressive-splitting-on-demand/webpack.config.js @@ -14,7 +14,7 @@ module.exports = { }) ], recordsInputPath: __dirname + "/input-records.json", - recordsOutputPath: __dirname + "/records.json", + //recordsOutputPath: __dirname + "/records.json", stats: { reasons: false, chunkModules: true,