Permalink
Browse files

Promise based chunk loading API

don't flag entry module with `0` id anymore
use extra argument in chunk instead
this allows to require entry points
  • Loading branch information...
sokra committed Jun 13, 2015
1 parent 66df346 commit 2245c4acca9c028b2b55c5cd7f1a933da605187a
Showing with 293 additions and 266 deletions.
  1. +9 −12 hot/dev-server.js
  2. +8 −11 hot/only-dev-server.js
  3. +9 −11 hot/poll.js
  4. +9 −11 hot/signal.js
  5. +1 −1 lib/APIPlugin.js
  6. +2 −2 lib/ChunkTemplate.js
  7. +3 −11 lib/Compilation.js
  8. +4 −1 lib/ContextModule.js
  9. +42 −51 lib/HotModuleReplacement.runtime.js
  10. +50 −47 lib/JsonpMainTemplatePlugin.js
  11. +16 −5 lib/MainTemplate.js
  12. +1 −1 lib/NodeStuffPlugin.js
  13. +3 −3 lib/RecordIdsPlugin.js
  14. +1 −1 lib/RequireJsStuffPlugin.js
  15. +2 −2 lib/dependencies/AMDRequireDependency.js
  16. +10 −10 lib/dependencies/DepBlockHelpers.js
  17. +1 −1 lib/dependencies/HarmonyModulesPlugin.js
  18. +8 −4 lib/dependencies/RequireEnsureDependency.js
  19. +3 −3 lib/node/NodeMainTemplate.runtime.js
  20. +12 −10 lib/node/NodeMainTemplateAsync.runtime.js
  21. +42 −14 lib/node/NodeMainTemplatePlugin.js
  22. +2 −2 lib/optimize/OccurrenceOrderPlugin.js
  23. +1 −1 package.json
  24. +1 −1 test/Compiler.test.js
  25. +0 −22 test/Errors.test.js
  26. +10 −3 test/HotModuleReplacementPlugin.test.js
  27. +6 −2 test/cases/chunks/runtime/index.js
  28. +3 −1 test/configCases/entry/issue-1068/test.js
  29. 0 test/{fixtures/errors/entry-point2.js → configCases/entry/require-entry-point/entry-point.js}
  30. 0 test/configCases/entry/require-entry-point/entry-point2.js
  31. +5 −0 test/configCases/entry/require-entry-point/require-entry-point.js
  32. +10 −0 test/configCases/entry/require-entry-point/webpack.config.js
  33. +0 −3 test/fixtures/errors/require-entry-point.js
  34. +16 −16 test/statsCases/chunks/expected.txt
  35. +1 −1 test/statsCases/external/expected.txt
  36. +1 −1 test/statsCases/simple-more-info/expected.txt
  37. +1 −1 test/statsCases/simple/expected.txt
@@ -9,18 +9,7 @@ if(module.hot) {
return lastData.indexOf(__webpack_hash__) >= 0;
};
var check = function check() {
module.hot.check(true, function(err, updatedModules) {
if(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot apply update. Need to do a full reload!");
console.warn("[HMR] " + err.stack || err.message);
window.location.reload();
} else {
console.warn("[HMR] Update failed: " + err.stack || err.message);
}
return;
}

module.hot.check(true).then(function(updatedModules) {
if(!updatedModules) {
console.warn("[HMR] Cannot find update. Need to do a full reload!");
console.warn("[HMR] (Probably because of restarting the webpack-dev-server)");
@@ -38,6 +27,14 @@ if(module.hot) {
console.log("[HMR] App is up to date.");
}

}).catch(function(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot apply update. Need to do a full reload!");
console.warn("[HMR] " + err.stack || err.message);
window.location.reload();
} else {
console.warn("[HMR] Update failed: " + err.stack || err.message);
}
});
};
var addEventListener = window.addEventListener ? function(eventName, listener) {
@@ -9,17 +9,7 @@ if(module.hot) {
return lastData.indexOf(__webpack_hash__) >= 0;
};
var check = function check() {
module.hot.check(function(err, updatedModules) {
if(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot check for update. Need to do a full reload!");
console.warn("[HMR] " + err.stack || err.message);
} else {
console.warn("[HMR] Update check failed: " + err.stack || err.message);
}
return;
}

module.hot.check().then(function(updatedModules) {
if(!updatedModules) {
console.warn("[HMR] Cannot find update. Need to do a full reload!");
console.warn("[HMR] (Probably because of restarting the webpack-dev-server)");
@@ -49,6 +39,13 @@ if(module.hot) {
console.log("[HMR] App is up to date.");
}
});
}).catch(function(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot check for update. Need to do a full reload!");
console.warn("[HMR] " + err.stack || err.message);
} else {
console.warn("[HMR] Update check failed: " + err.stack || err.message);
}
});
};
var addEventListener = window.addEventListener ? function(eventName, listener) {
@@ -7,23 +7,21 @@ if(module.hot) {
var hotPollInterval = +(__resourceQuery.substr(1)) || (10 * 60 * 1000);
function checkForUpdate(fromUpdate) {
if(module.hot.status() === "idle") {
module.hot.check(true, function(err, updatedModules) {
if(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot apply update.");
console.warn("[HMR] " + err.stack || err.message);
console.warn("[HMR] You need to restart the application!");
} else {
console.warn("[HMR] Update failed: " + err.stack || err.message);
}
return;
}
module.hot.check(true).then(function(updatedModules) {
if(!updatedModules) {
if(fromUpdate) console.log("[HMR] Update applied.");
return;
}
require("./log-apply-result")(updatedModules, updatedModules);
checkForUpdate(true);
}).catch(function(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot apply update.");
console.warn("[HMR] " + err.stack || err.message);
console.warn("[HMR] You need to restart the application!");
} else {
console.warn("[HMR] Update failed: " + err.stack || err.message);
}
});
}
}
@@ -5,17 +5,7 @@
/*globals __resourceQuery */
if(module.hot) {
function checkForUpdate(fromUpdate) {
module.hot.check(function(err, updatedModules) {
if(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot apply update.");
console.warn("[HMR] " + err.stack || err.message);
console.warn("[HMR] You need to restart the application!");
} else {
console.warn("[HMR] Update failed: " + err.stack || err.message);
}
return;
}
module.hot.check().then(function(updatedModules) {
if(!updatedModules) {
if(fromUpdate)
console.log("[HMR] Update applied.");
@@ -42,6 +32,14 @@ if(module.hot) {

checkForUpdate(true);
});
}).catch(function(err) {
if(module.hot.status() in {abort: 1, fail: 1}) {
console.warn("[HMR] Cannot apply update.");
console.warn("[HMR] " + err.stack || err.message);
console.warn("[HMR] You need to restart the application!");
} else {
console.warn("[HMR] Update failed: " + err.stack || err.message);
}
});
}

@@ -17,7 +17,7 @@ var REPLACEMENTS = {
__webpack_modules__: "__webpack_require__.m", // eslint-disable-line camelcase
__webpack_chunk_load__: "__webpack_require__.e", // eslint-disable-line camelcase
__non_webpack_require__: "require", // eslint-disable-line camelcase
"require.onError": "__webpack_require__.onError" // eslint-disable-line camelcase
"require.onError": "__webpack_require__.oe" // eslint-disable-line camelcase
};
var REPLACEMENT_TYPES = {
__webpack_public_path__: "string", // eslint-disable-line camelcase
@@ -17,7 +17,7 @@ ChunkTemplate.prototype.render = function(chunk, moduleTemplate, dependencyTempl
var core = this.applyPluginsWaterfall("modules", modules, chunk, moduleTemplate, dependencyTemplates);
var source = this.applyPluginsWaterfall("render", core, chunk, moduleTemplate, dependencyTemplates);
if(chunk.modules.some(function(module) {
return (module.id === 0);
return (module.entry);
})) {
source = this.applyPluginsWaterfall("render-with-entry", source, chunk);
}
@@ -29,4 +29,4 @@ ChunkTemplate.prototype.updateHash = function(hash) {
hash.update("ChunkTemplate");
hash.update("2");
this.applyPlugins("hash", hash);
};
};
@@ -43,7 +43,7 @@ function Compilation(compiler) {
this._modules = {};
this.cache = null;
this.records = null;
this.nextFreeModuleId = 1;
this.nextFreeModuleId = 0;
this.nextFreeChunkId = 0;
this.nextFreeModuleIndex = 0;
this.nextFreeModuleIndex2 = 0;
@@ -241,12 +241,6 @@ Compilation.prototype.addModuleDependencies = function(module, dependencies, bai
dependantModule.optional = isOptional();
}

if(dependantModule.id === 0) {
return errorOrWarningAndCallback(
new ModuleNotFoundError(module, new Error("a dependency to an entry point is not allowed"))
);
}

dependencies.forEach(function(dep) {
dep.module = dependantModule;
dependantModule.addReason(module, dep);
@@ -418,17 +412,14 @@ Compilation.prototype.addEntry = function process(context, entry, name, callback
entry.module = module;
this.entries.push(module);
module.issuer = null;
module.id = 0;
module.entry = true;

}.bind(this), function(err, module) {
if(err) {
return callback(err);
}

if(module) {
if(module.reasons.length > 0) {
return callback(new Error("module cannot be added as entry point, because it's already in the bundle"));
}
this.preparedChunks.push({
name: name,
module: module
@@ -491,6 +482,7 @@ Compilation.prototype.seal = function seal(callback) {
chunk.initial = chunk.entry = true;
chunk.addModule(module);
module.addChunk(chunk);
chunk.entryModule = module;
if(typeof module.index !== "number") {
module.index = this.nextFreeModuleIndex++;
}
@@ -95,7 +95,10 @@ ContextModule.prototype.source = function() {
"\treturn __webpack_require__(webpackContextResolve(req));\n",
"};\n",
"function webpackContextResolve(req) {\n",
"\treturn map[req] || (function() { throw new Error(\"Cannot find module '\" + req + \"'.\") }());\n",
"\tvar id = map[req];\n",
"\tif(!(id + 1)) // check for number\n",
"\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n",
"\treturn id;\n",
"};\n",
"webpackContext.keys = function webpackContextKeys() {\n",
"\treturn Object.keys(map);\n",
@@ -32,28 +32,25 @@ module.exports = function() {
fn[name] = $require$[name];
}
}
fn.e = function(chunkId, callback) {
fn.e = function(chunkId) {
if(hotStatus === "ready")
hotSetStatus("prepare");
hotChunksLoading++;
$require$.e(chunkId, function() {
try {
callback.call(null, fn);
} finally {
finishChunkLoading();
}
function finishChunkLoading() {
hotChunksLoading--;
if(hotStatus === "prepare") {
if(!hotWaitingFilesMap[chunkId]) {
hotEnsureUpdateChunk(chunkId);
}
if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
hotUpdateDownloaded();
}
return $require$.e(chunkId).then(finishChunkLoading, function(err) {
finishChunkLoading();
throw err;
});
function finishChunkLoading() {
hotChunksLoading--;
if(hotStatus === "prepare") {
if(!hotWaitingFilesMap[chunkId]) {
hotEnsureUpdateChunk(chunkId);
}
if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
hotUpdateDownloaded();
}
}
});
}
};
return fn;
}
@@ -134,27 +131,19 @@ module.exports = function() {
var hotWaitingFilesMap = {};
var hotRequestedFilesMap = {};
var hotAvailibleFilesMap = {};
var hotCallback;
var hotDeferred;

// The update info
var hotUpdate, hotUpdateNewHash;

function hotCheck(apply, callback) {
function hotCheck(apply) {
if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
if(typeof apply === "function") {
hotApplyOnUpdate = false;
callback = apply;
} else {
hotApplyOnUpdate = apply;
callback = callback || function(err) { if(err) throw err; };
}
hotApplyOnUpdate = apply;
hotSetStatus("check");
hotDownloadManifest(function(err, update) {
if(err) return callback(err);
return hotDownloadManifest().then(function(update) {
if(!update) {
hotSetStatus("idle");
callback(null, null);
return;
return null;
}

hotRequestedFilesMap = {};
@@ -165,7 +154,12 @@ module.exports = function() {
hotUpdateNewHash = update.h;

hotSetStatus("prepare");
hotCallback = callback;
var promise = new Promise(function(resolve, reject) {
hotDeferred = {
resolve: resolve,
reject: reject
};
});
hotUpdate = {};
/*foreachInstalledChunks*/ { // eslint-disable-line no-lone-blocks
/*globals chunkId */
@@ -174,6 +168,7 @@ module.exports = function() {
if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) {
hotUpdateDownloaded();
}
return promise;
});
}

@@ -203,33 +198,29 @@ module.exports = function() {

function hotUpdateDownloaded() {
hotSetStatus("ready");
var callback = hotCallback;
hotCallback = null;
if(!callback) return;
var deferred = hotDeferred;
hotDeferred = null;
if(!deferred) return;
if(hotApplyOnUpdate) {
hotApply(hotApplyOnUpdate, callback);
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)) {
outdatedModules.push(+id);
}
}
callback(null, outdatedModules);
deferred.resolve(outdatedModules);
}
}

function hotApply(options, callback) {
function hotApply(options) {
if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status");
if(typeof options === "function") {
callback = options;
options = {};
} else if(options && typeof options === "object") {
callback = callback || function(err) { if(err) throw err; };
} else {
options = {};
callback = callback || function(err) { if(err) throw err; };
}
options = options || {};

function getAffectedStuff(module) {
var outdatedModules = [module];
@@ -289,11 +280,11 @@ module.exports = function() {
if(options.ignoreUnaccepted)
continue;
hotSetStatus("abort");
return callback(new Error("Aborted because " + moduleId + " is not accepted"));
return Promise.reject(new Error("Aborted because " + moduleId + " is not accepted"));
}
if(result instanceof Error) {
hotSetStatus("abort");
return callback(result);
return Promise.reject(result);
}
appliedUpdate[moduleId] = hotUpdate[moduleId];
addAllToSet(outdatedModules, result[0]);
@@ -426,10 +417,10 @@ module.exports = function() {
// handle errors in accept handlers and self accepted module load
if(error) {
hotSetStatus("fail");
return callback(error);
return Promise.reject(error);
}

hotSetStatus("idle");
callback(null, outdatedModules);
Promise.resolve(outdatedModules);
}
};
};
Oops, something went wrong.

1 comment on commit 2245c4a

@gaearon

This comment has been minimized.

Copy link
Contributor

gaearon commented on 2245c4a Jun 15, 2015

I'm getting errors on hot reloading, it seems that JsonpMainTemplate still uses the callback form of hotDownloadManifest.

Please sign in to comment.