Node.js中是否可克隆vm模块创建的上下文(context)?
克隆Node.js VM上下文的实现方法
问题背景
初始代码如下:
import vm from 'node:vm'; const context = { foo: {}, }; vm.createContext(context); vm.runInContext('const foo = {}', context);
需要实现一个clone方法,达到以下效果:
const a = clone(context); const b = clone(context); vm.runInContext('foo.bar = "A"', a); vm.runInContext('foo.bar = "B"', b); a.foo.bar === 'A'; // 预期为true b.foo.bar === 'B'; // 预期为true
要求克隆后的上下文a和b修改foo属性时互不影响,各自属性值符合预期。
解决方案
直接用浅拷贝或深拷贝普通对象的路子搞不定VM上下文,因为vm.createContext会给对象加一堆特殊内部属性和代理逻辑。正确的做法是重新造一个新上下文对象,把原上下文的属性搬过去,再重新初始化VM上下文和里面的变量。
具体实现
import vm from 'node:vm'; // 把初始化上下文的代码单独拎出来,方便复用 const initCode = 'const foo = {}'; const context = { foo: {}, }; vm.createContext(context); vm.runInContext(initCode, context); // 实现clone函数 function clone(originalContext) { // 1. 创建新对象,复制原上下文的可枚举属性 const newContext = Object.assign({}, originalContext); // 2. 为新对象创建VM上下文 vm.createContext(newContext); // 3. 执行初始化代码,确保内部变量独立 vm.runInContext(initCode, newContext); return newContext; } // 测试效果 const a = clone(context); const b = clone(context); vm.runInContext('foo.bar = "A"', a); vm.runInContext('foo.bar = "B"', b); console.log(a.foo.bar === 'A'); // true console.log(b.foo.bar === 'B'); // true
关键说明
- 为啥不能直接拷贝?因为
vm.createContext会给对象添加内部的[[Context]]标记,普通拷贝方法复制不了这些内部属性,新对象就没法作为有效的VM上下文使用。 - 必须重新执行初始化代码:原上下文内通过
const foo = {}定义的变量是绑定在VM上下文作用域里的,只有重新执行这段代码,才能在新上下文里生成独立的foo实例,确保多个克隆上下文之间的修改互不干扰。
内容的提问来源于stack exchange,提问作者Gajus
相关产品推荐
相关产品推荐

