Open nithiwatter opened 1 year ago
I managed to import all methods of lodash programmatically by looping through them, setting them to the global context, and reassigning them to a new variable. My method only works for static methods though, class instances using "this" will be broken. Not sure if it helps.
const myLibs = { lodash, someOtherStaticLib };
const isolate = new ivm.Isolate({ memoryLimit: 8 });
const context = isolate.createContextSync();
const jail = context.global;
jail.setSync('global', jail.derefInto());
jail.setSync('ivm', ivm);
let scriptLines: string[] = [];
if (myLibs) {
Object.entries(myLibs).forEach(([libName, libValue]) => {
// creating empty object with the name of the lib
scriptLines.push(`globalThis.${libName} = {}`);
const lib = libValue as Record<string, unknown>;
// reconstructing the lib by iterating through all of its methods, setting them to the global object, and reassigning them to the created object
Object.keys(lib).forEach((method) => {
if (Object.prototype.hasOwnProperty.call(lib, method) && typeof lib[method] === 'function') {
jail.setSync(`ref_${libName}_${method}`, lib[method]);
scriptLines.push(`globalThis.${libName}.${method} = ref_${libName}_${method};`);
}
});
});
}
// these lines allow to retrieve non-primary values (otherwise arrays and objects return undefined)
scriptLines.push(`const evalResult = eval(${JSON.stringify(statement)});`);
scriptLines.push(`new ivm.Reference(evalResult);`);
const result = isolate.compileScriptSync(scriptLines.join('\n')).runSync(context);
const value = result.copySync();
Why not just evaluate the source of lodash from within the isolate?
Are you referring to this method ? https://github.com/laverdet/isolated-vm/issues/199#issuecomment-695114062 In my case, I was using vm2 before it got deprecated, and am trying to replicate the ability to import libraries dynamically, but while static objects seem to work fine, I haven't had any success with class instances (it breaks when hitting a "this.[method]"). Do you think it's possible ?
It helps to think of isolated-vm like a browser. How would you transfer an instantiated class from nodejs to Chrome? You can't! In the case of lodash the answer is to just send the code to isolated-vm in the same way would send it to a client.
Thanks @laverdet for the awesome tool and thanks for giving that webpack solution in the other thread: https://github.com/laverdet/isolated-vm/issues/199#issuecomment-695114062
I prefer requiring modules to be loaded into the context ahead of time (rather than dynamically). Seems like a safer runtime design
Hey @laverdet, I started migrating from vm2 and now currently I'm trying to import module like this:
const code = `import Component from '/build/model/event/component.js';`;
const module = await isolate.compileModule(code);
await module.instantiate(context, (s, r) => {
let m = fs.readFileSync(s).toString()
return isolate.compileModuleSync(m)
})
module.evaluateSync()
jail.setSync("component", module.namespace.derefInto({release:true}))
component.js file:
export default class Component {
constructor() {}
method1() {}
method2() {}
}
I'm not getting errors, but now I don't know how to use this module, for example, running this code new Component()
gives me an error Component is not defined
.
What am I doing wrong here?
Your code is incomplete. I can't help you unless you post a complete example.
Well lets say we build a module like in the code example I provided and now you want to use it in the code:
const hostile = isolate.compileScriptSync(`
const c = new Component();
`);
hostile.run(context).catch(err => console.error(err));
or
const hostile = isolate.compileScriptSync(`
const c = new component();
`);
hostile.run(context).catch(err => console.error(err));
This will throw Component is not defined
.
You are posting code fragments. You need to post a complete program. I can't just guess what the rest of the code looks like. Put yourself in my shoes, I can't troubleshoot the program that you haven't given me.
What is the best way in general to import modules like
crypto
andfetch
without making wrapper methods. Currently, we are passing these methods via the references. However, assuming that crypto has many methods, it would be a bit of work to make wrappers for all methods of this module. Thank you!