You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cachedData创建vm.SourceTextModule时触发TypeError问题咨询

问题分析与解决方案

不是设置cachedData后就无法使用import()语法,问题出在缓存数据的创建时机和回调绑定的逻辑上。

核心原因

调用mod1.createCachedData()时,缓存数据仅包含模块编译阶段的信息,此时模块尚未触发动态导入逻辑,且importModuleDynamically回调不会被序列化到缓存中。当用该缓存创建mod2时,Node.js处理动态导入时无法从缓存中找到回调关联,即便创建mod2时传入了回调,也会因缓存优先级导致回调未被正确绑定。

解决方案

调整缓存创建时机,确保动态导入的回调逻辑在缓存生成前已被正确关联。具体来说,需先完成模块的link操作,再生成缓存数据:

import vm from "vm";

let context = vm.createContext({console})

async function importModuleDynamically(name) {
    let stt = new vm.SyntheticModule(['name'], function () {
        this.setExport('name', name)
    })
    await stt.link(() => null)
    await stt.evaluate()
    return stt
}

function initializeImportMeta(meta, module) {
    meta.url = module.identifier
}

let code = 'export default () => import("fs")'

// 先创建模块并完成link,确保动态导入回调被关联后再生成缓存
let mod1 = new vm.SourceTextModule(code, {
    context,
    identifier: 'mod1',
    importModuleDynamically,
    initializeImportMeta
})

// 先执行link,让Node.js识别动态导入的回调依赖
await mod1.link(() => null)
// 此时生成的缓存会包含动态导入的绑定信息
let cachedData = mod1.createCachedData()

await mod1.evaluate()
console.log(await mod1.namespace.default())


let mod2 = new vm.SourceTextModule(code, {
    context,
    identifier: 'mod1',
    cachedData,
    importModuleDynamically,
    initializeImportMeta
})

await mod2.link(() => null)
await mod2.evaluate()
console.log(await mod2.namespace.default())

console.log(mod1, mod2)

关键说明

  • createCachedData()必须在模块link之后调用,这样缓存才会包含模块对动态导入回调的依赖标记,后续用缓存创建模块时,传入的importModuleDynamically才能被正确识别。
  • Node.js的vm模块缓存不会存储回调函数本身,仅存储模块结构和依赖关系,因此必须提前通过link让模块标记动态导入需求,确保后续回调生效。

内容的提问来源于stack exchange,提问作者Time Killer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:25:03