Как связать с ним импортированные зависимости модуля, созданного vm.SourceTextModule?
Допустим, мы создаем модуль, вызываемый путем построения нового
vm.SourceTextModule
объект:
const context = {
exports: {},
console, // custom console object
};
const sandbox = vm.createContext(context);
const app = new vm.SourceTextModule(
`import path from 'path';
console.log(path.resolve('./src'));`,
{
context: sandbox,
}
);
Согласно документации Node.js , чтобы получить экспорт по умолчанию из модуля, мы должны «привязать» к нему импортированные зависимости модуля.
Для этого мы должны передать обратный вызов
app.link
метод:
async function linker(specifier, referencingModule) {
// the desired logic...
}
await app.link(linker);
Как реализовать
linker
функционировать должным образом, чтобы мы могли импортировать модуль во вновь созданный
app
модуль и используйте его:
await app.evaluate(); // => /home/user/Documents/project/src
P.S. Мы используем
TypeScript
, поэтому я проверил, установлены ли у нас типы для
path
упаковка.
пакет.json:
"@types/node": "^17.0.31",
1 ответ
Я нашел https://github.com/nodejs/node/issues/35848 , где кто-то разместил фрагмент кода.
Оттуда я адаптировал следующий обратный вызов компоновщика:
const imports = new Map();
async function linker(specifier, referencingModule) {
if (imports.has(specifier))
return imports.get(specifier);
const mod = await import(specifier);
const exportNames = Object.keys(mod);
const imported = new vm.SyntheticModule(
exportNames,
() => {
// somehow called with this === undefined?
exportNames.forEach(key => imported.setExport(key, mod[key]));
},
{ identifier: specifier, context: referencingModule.context }
);
imports.set(specifier, imported);
return imported;
}
Фрагмент кода из проблемы GitHub не работал у меня на Node 18.7.0 как есть, потому что обратный вызов оценщика передавался конструкторуSyntheticModule
как-то называется сthis
установлен вundefined
. Это может быть ошибка узла.
Я также кэшировал импортированные SyntheticModules на карте, потому что, если они имеют внутреннее состояние, создание нового SyntheticModule каждый раз будет сбрасывать это состояние.