Walk dynamic module graph synchronously.

I made this code asynchronous at first to accommodate the asynchronous
cache API, but walking the graph needs to happen synchronously so that
near-simultaneous dynamic import(...)s do not interleave.
This commit is contained in:
Ben Newman
2017-02-16 16:38:11 -05:00
parent eadd954115
commit edb4e0664c

View File

@@ -18,56 +18,45 @@ Module.prototype.dynamicImport = function (id) {
throw error;
}
// Require the current module from the complete meta graph.
// Require the parent module from the complete meta graph.
var meta = requireMeta(module.id);
var missingTree;
var localTree;
var versions = Object.create(null);
function walk(meta) {
if (meta.dynamic) {
return meta.pending || (meta.pending = add(
meta.module.id,
meta.version
).then(function () {
return allChildren(meta, walkChild);
}));
if (meta.dynamic && ! meta.pending) {
meta.pending = true;
versions[meta.module.id] = meta.version;
meta.eachChild(walkChild);
}
}
function add(id, version) {
return cache.check(id, version).then(function (code) {
addToTree(localTree = localTree || Object.create(null), id, code);
}, function (missing) {
addToTree(missingTree = missingTree || Object.create(null), id, 1);
});
}
function walkChild(childModule) {
return walk(childModule.exports);
}
return allChildren(meta, walkChild, [id]).then(function () {
meta.eachChild(walkChild, [id]);
var localTree;
var missingTree;
return Promise.all(Object.keys(versions).map(function (id) {
return cache.check(id, versions[id]).then(function (code) {
addToTree(localTree = localTree || Object.create(null), id, code);
}, function (missing) {
addToTree(missingTree = missingTree || Object.create(null), id, 1);
});
})).then(function () {
if (localTree) {
installResults(localTree);
}
return missingTree && fetchMissing(missingTree);
}).then(get);
});
};
// The allChildren iteration includes all child modules imported by
// meta.module, not just the child explicitly required here, so that
// implicit modules like package.json will be included too.
function allChildren(meta, callback, idsToRequire) {
var results = [];
// See meteor/packages/modules-runtime/meteor-install.js for the
// definition of meta.eachChild.
meta.eachChild(function (child) {
results.push(callback(child));
}, idsToRequire);
return Promise.all(results);
}
function fetchMissing(missingTree) {
return new Promise(function (resolve, reject) {
Meteor.call(