The use of eval in vm is restricted
runtime.getExecutor("""
const vm = require('node:vm');
const script = new vm.Script("eval('1+1')");
script.runInNewContext();
""".trimIndent()).setModule(true).executeVoid()
It's normal to write like this. But
runtime.getExecutor("""
const vm = require('node:vm');
const script = new vm.Script("eval('1+1')");
script.runInNewContext();
""".trimIndent()).compileV8Module().execute();
Will throw an error:EvalError: Code generation from strings disallowed for this context
So this is a bug?
It seems you are using the engine pool which disables eval() by default. Please check this page out to allow eval().
I set allowEval to true, but it doesn't seem to work.
It's more like a JS trick as follows.
nodeRuntime.allowEval(true);
nodeRuntime.getExecutor("const vm = require(\"node:vm\");\n" +
"const script = new vm.Script(\"eval('1+1')\");\n" +
"console.log(script.runInThisContext());\n" +
"console.log(script.runInNewContext(vm.createContext({eval})));").executeVoid();
// Output
2
2
Have you tried .compileV8Module().execute()? This is when an error would be thrown, whereas .executeVoid() works without issues. I needed to use .compileV8Module() in IV8ModuleResolver.resolve() and that's how I discovered this problem.
Those API require certain understanding on how V8 works internally. Please let your code.
fun resolve(runtime: V8Runtime, resourceName: String, v8ModuleReferrer: IV8Module): Any? {
return when {
resourceName.startsWith("/") || resourceName.startsWith("./") || resourceName.startsWith("../") -> {
val parentModuleName = v8ModuleReferrer.getResourceName()
val moduleRelativePath = Paths.get(parentModuleName).parent.resolve(resourceName).normalize()
val moduleFile = Paths.get(localRelativePath).resolve(moduleRelativePath).toFile()
if (moduleFile.exists() && moduleFile.isFile) {
val url = "file://${moduleFile.canonicalPath}"
val code = readFile(url)
runtime.getExecutor("import.meta.url=${Json.encodeToString(url)};$code")
.setResourceName(moduleRelativePath.toString()).compileV8Module()
} else {
null
}
}
resourceName.startsWith("node:") -> nodeResolve.resolve(runtime, resourceName, v8ModuleReferrer)
else -> {
val moduleObject = runtime.getNodeModule(resourceName, nodeModuleAnyClazz).getModuleObject()
moduleObject.set("default", moduleObject)
runtime.createV8Module(resourceName, moduleObject)
}
}
}
This is my code. So, how do we address the issues with eval?
It doesn't seem to be a complete reproducible code. Could you leave a repo with the issue?
It's more like a JS trick as follows.
nodeRuntime.allowEval(true); nodeRuntime.getExecutor("const vm = require(\"node:vm\");\n" + "const script = new vm.Script(\"eval('1+1')\");\n" + "console.log(script.runInThisContext());\n" + "console.log(script.runInNewContext(vm.createContext({eval})));").executeVoid(); // Output 2 2
I just realized that this eval is manually injected into the vm context, while in fact, native Node.js does not require such an operation.
native Node.js:
javet:
It's more like a JS trick as follows.
nodeRuntime.allowEval(true); nodeRuntime.getExecutor("const vm = require(\"node:vm\");\n" + "const script = new vm.Script(\"eval('1+1')\");\n" + "console.log(script.runInThisContext());\n" + "console.log(script.runInNewContext(vm.createContext({eval})));").executeVoid(); // Output 2 2
Can you take a look at it for me?
const vm = require('vm');
// 创建一个沙箱上下文 const sandbox = { x: 1, y: 2 };
// 创建一个虚拟机上下文,允许执行 eval vm.createContext(sandbox);
// 使用 vm.runInContext 执行代码 const code = 'eval("x + y")'; // 使用 eval 来执行动态代码 const result = vm.runInContext(code, sandbox);
console.log(result); // 输出: 3 在这个例子中,通过 vm.createContext 创建了一个沙箱,并在该上下文中执行了一个包含 eval() 的动态代码。正常环境 这个代码被允许执行,因为 eval 在上下文中没有被禁用。但是javet 运行结果是eval不能正确执行, 可能是处于禁用。
v8Isolate->SetModifyCodeGenerationFromStringsCallback(nullptr); 不知道这段代码是用来干什么的 注释掉 vm eavl 开启和禁用 问题解决