我正在做类似的事情
let p = `(function (X) {
var q = 0;
for (; q < 5; ) {
// do some stuff
anotherfunc = function (a) {
while (X === "somestring") {
X += "_";
}
};
q++;
}
return { anotherfunc: anotherfunc };
})("some arg");
`;
const vm = require("vm");
const script = new vm.Script(p);
const context = vm.createContext({});
const result = script.runInContext(context);
console.log(result);
我得到
{ anotherfunc: ƒ anotherfunc() }
打印,但如果我使用 JSON.stringify(result)
我得到 "{}"
我想要得到类似的东西
{
anotherfunc: function (a) {
while (X === "somestring") {
X += "_";
}
};
}
为了将其传递给
acorn.parse
并获取 AST 表示。
有没有办法让
script.runInContext
将结果保存到文件中,或者让acorn
解析不是字符串的result
?
尝试一下。
const vm = require("vm");
const acorn = require("acorn");
let p = `(function (X) {
var q = 0;
for (; q < 5; ) {
// do some stuff
anotherfunc = function (a) {
while (X === "somestring") {
X += "_";
}
};
q++;
}
return { anotherfunc: anotherfunc };
})("some arg");
`;
const script = new vm.Script(p);
const context = vm.createContext({});
const result = script.runInContext(context);
// Extract the function source code
const functionSourceCode = result.anotherfunc.toString();
// Parse the function source code using acorn
const ast = acorn.parse(functionSourceCode, { ecmaVersion: 2020 });
console.log(JSON.stringify(ast, null, 2));
我最终得到的当前解决方案如下(在 ChatGPT 的帮助下)。请随意提出其他更强大的解决方案......或改进这个:
const vm = require("vm");
// Example code to run
let p = `(function (X) {
var q = 0;
for (; q < 5; ) {
anotherfunc = function (a) {
while (X === "somestring") {
X += "_";
}
};
q++;
}
return { anotherfunc: anotherfunc, nested: { funcInside: function() { return "inner"; }, num: 42 }, str: "hello" };
})("some arg");
`;
const script = new vm.Script(p);
const context = vm.createContext({});
const result = script.runInContext(context);
// Recursive function to handle all types
function stringifyResult(value) {
// 1. Handle functions first (convert function to string)
if (typeof value === 'function') {
return value.toString();
}
// 2. Base case for primitives (string, number, etc.)
if (value === null || value === undefined || typeof value !== 'object') {
return JSON.stringify(value);
}
// 3. Handle arrays
if (Array.isArray(value)) {
return `[${value.map(item => stringifyResult(item)).join(', ')}]`;
}
// 4. Handle objects (including nested objects)
if (typeof value === 'object') {
let result = '{';
for (let key in value) {
if (value.hasOwnProperty(key)) {
result += `${JSON.stringify(key)}: ${stringifyResult(value[key])}, `;
}
}
result = result.slice(0, -2) + '}'; // Remove the last comma and space
return result;
}
return '{}';
}
// Apply the function to the result
const stringifiedResult = stringifyResult(result);
// Log the result (string representation of the entire structure)
console.log(stringifiedResult);