Как связать с ним импортированные зависимости модуля, созданного 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 каждый раз будет сбрасывать это состояние.

Другие вопросы по тегам