mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
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:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user