mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
This prevents __dynamicImport from blocking other method calls made by the application, but introduces the possibility that __dynamicImport method results could be delivered out of order, which is now handled in the fetchMissing function.
77 lines
2.0 KiB
JavaScript
77 lines
2.0 KiB
JavaScript
import assert from "assert";
|
|
import { readFileSync } from "fs";
|
|
import {
|
|
join as pathJoin,
|
|
normalize as pathNormalize,
|
|
} from "path";
|
|
|
|
import { check } from "meteor/check";
|
|
|
|
import "./security.js";
|
|
import "./client.js";
|
|
|
|
const hasOwn = Object.prototype.hasOwnProperty;
|
|
|
|
Object.keys(dynamicImportInfo).forEach(platform => {
|
|
const info = dynamicImportInfo[platform];
|
|
if (info.dynamicRoot) {
|
|
info.dynamicRoot = pathNormalize(info.dynamicRoot);
|
|
}
|
|
});
|
|
|
|
Meteor.methods({
|
|
__dynamicImport(tree) {
|
|
check(tree, Object);
|
|
this.unblock();
|
|
|
|
const platform = this.connection ? "web.browser" : "server";
|
|
const pathParts = [];
|
|
|
|
function walk(node) {
|
|
if (node && typeof node === "object") {
|
|
Object.keys(node).forEach(name => {
|
|
pathParts.push(name);
|
|
node[name] = walk(node[name]);
|
|
assert.strictEqual(pathParts.pop(), name);
|
|
});
|
|
} else {
|
|
return read(pathParts, platform);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
return walk(tree);
|
|
}
|
|
});
|
|
|
|
function read(pathParts, platform) {
|
|
const { dynamicRoot } = dynamicImportInfo[platform];
|
|
const absPath = pathNormalize(pathJoin(dynamicRoot, ...pathParts));
|
|
|
|
if (! absPath.startsWith(dynamicRoot)) {
|
|
throw new Meteor.Error("bad dynamic module path");
|
|
}
|
|
|
|
const cache = getCache(platform);
|
|
return hasOwn.call(cache, absPath)
|
|
? cache[absPath]
|
|
: cache[absPath] = readFileSync(absPath, "utf8");
|
|
}
|
|
|
|
const cachesByPlatform = Object.create(null);
|
|
function getCache(platform) {
|
|
return hasOwn.call(cachesByPlatform, platform)
|
|
? cachesByPlatform[platform]
|
|
: cachesByPlatform[platform] = Object.create(null);
|
|
}
|
|
|
|
process.on("message", msg => {
|
|
// The cache for the "web.browser" platform needs to be discarded
|
|
// whenever a client-only refresh occurs, so that new client code does
|
|
// not receive stale module data from __dynamicImport. This code handles
|
|
// the same message listened for by the autoupdate package.
|
|
if (msg && msg.refresh === "client") {
|
|
delete cachesByPlatform["web.browser"];
|
|
}
|
|
});
|