Files
meteor/packages/dynamic-import/dynamic-versions.js
2020-12-11 13:26:21 +01:00

108 lines
3.2 KiB
JavaScript

// This magic double-underscored identifier gets replaced in
// tools/isobuild/bundler.js with a tree of hashes of all dynamic
// modules, for use in client.js and cache.js.
var versions = __DYNAMIC_VERSIONS__;
const METEOR_PREFIX = '/node_modules/meteor/';
exports.get = function (id) {
var tree = versions;
var version = null;
id.split("/").some(function (part) {
if (part) {
// If the tree contains identifiers for Meteor packages with colons
// in their names, the colons should not have been replaced by
// underscores, but there's a bug that results in that behavior, so
// for now it seems safest to be tolerant of underscores here.
// https://github.com/meteor/meteor/pull/9103
tree = tree[part] || tree[part.replace(":", "_")];
}
if (! tree) {
// Terminate the search without reassigning version.
return true;
}
if (typeof tree === "string") {
version = tree;
return true;
}
});
return version;
};
function getFlatModuleArray(tree) {
var parts = [""];
var result = [];
function walk(t) {
if (t && typeof t === "object") {
Object.keys(t).forEach(function (key) {
parts.push(key);
walk(t[key]);
parts.pop();
});
} else if (typeof t === "string") {
result.push(parts.join("/"));
}
}
walk(tree);
return result;
}
// If Package.appcache is loaded, preload additional modules after the
// core bundle has been loaded.
function precacheOnLoad(event) {
// Check inside onload to make sure Package.appcache has had a chance to
// become available.
if (! Package.appcache) {
return;
}
// Prefetch in chunks to reduce overhead. If we call module.prefetch(id)
// multiple times in the same tick of the event loop, all those modules
// will be fetched in one HTTP POST request.
function prefetchInChunks(modules, amount) {
Promise.all(modules.splice(0, amount).map(function (id) {
return new Promise(function (resolve, reject) {
module.prefetch(id).then(resolve).catch(
function (err) {
// we probably have a : _ mismatch
// what can get wrong if we do the replacement
// 1. a package with a name like a_b:package will not resolve
// 2. someone falsely imports a_package that does not exist but a
// package a:package exists, so this one gets imported and its usage
// will fail
if (id.indexOf(METEOR_PREFIX) === 0) {
module.prefetch(
METEOR_PREFIX + id.replace(METEOR_PREFIX, '').replace('_', ':')
).then(resolve).catch(reject);
} else {
reject(err);
}
})
});
})).then(function () {
if (modules.length > 0) {
setTimeout(function () {
prefetchInChunks(modules, amount);
}, 0);
}
});
}
// Get a flat array of modules and start prefetching.
prefetchInChunks(getFlatModuleArray(versions), 50);
}
// Use window.onload to only prefetch after the main bundle has loaded.
if (global.addEventListener) {
global.addEventListener('load', precacheOnLoad, false);
} else if (global.attachEvent) {
global.attachEvent('onload', precacheOnLoad);
}