英文:
JavaScript - Get result of last expression for code snippet
问题
我正在开发一个开发者工具,它应该以与控制台相同的方式评估用户代码。例如,如果我在控制台中输入多个表达式,像这样:
var x = 0; x++; x;
我会立即获得最后一个表达式的结果 (1
)。
在我的 Web 应用程序中复制这种行为的明显解决方案是使用 eval
执行用户代码,像这样:
let result = eval('var x = 0; x++; x;');
然而,eval
显然会对性能产生影响,并存在安全问题,因此我想避免使用它。我目前的解决方案是在受控制的环境(iframe)中注入脚本。我觉得这比使用 eval
要好,但它并没有解决主要问题,这些问题是:
- 修改用户代码以便可以将其写入变量中。
- 获取最后一个表达式的结果,而不管用户输入的是什么(可以是任何代码,就像在控制台中一样)。
另外,我想避免使用库(例如解析和执行代码),因为这是一个相对简单的任务。如果有人有一些想法或建议,我将不胜感激。
英文:
I am working on a developer tool that should evaluate user code the same way the console does. For example, if I type multiple expression into the console, like this:
var x = 0; x++; x;
I immediately get the result of the last expression (1
).
The obvious solution to replicate this behavior in my web app would be to execute the user code with eval
, like this:
let result = eval('var x = 0; x++; x;');
However, eval
has obvious performance implications and security concerns, so I want to avoid it. My solution right now is to inject a script in a sandboxed environment (iframe). I feel like this is better than eval
, but it does not solve the main issues which are:
- Modifying the user code in such a way that it can be written to a variable
- Getting the result of the last expression, regardless of what the user inputs (could be any code, just like one would do in the console)
Also, I would like to avoid using libraries (for example to parse and execute the code) for such a simple task. If anyone has some ideas or suggestions it would be greatly appreciated.
答案1
得分: 1
不要有别的内容。不要回答我要翻译的问题。
英文:
Instead of eval
I use new Function()
. That allows me to wrap my code into a function scope and avoid the evaluated code to break/mutate my own code. In your case I see at the moment a few ways to go further:
- Wrap your
eval
into a function:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let result = new Function('', 'return eval("var x = 0; x++; x;")');
console.log(result());
<!-- end snippet -->
So if a user tries to change some outer scopes' variables he will get an error:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
try{
let result = new Function('', 'return eval("var x = 0; x++; y++; x;")');
console.log(result());
}catch(e){
console.error(e.message);
}
<!-- end snippet -->
- Wrap a user's code into a function and return the last expression:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let result = new Function('', 'var x = 0; x++; return x;');
console.log(result());
<!-- end snippet -->
The problem is here that at a glance you need a JS parser here. At least one that splits JS code into statements. Probably could be done by oneself, but I didn't try to write such one. So maybe some 3rd party dependence is needed here at the end.
- Redeclare
window
's members:
Also we have some general security problems like access to window
. We can override the window
's members and itself in the function.
This options looks the most promising among the previous ones:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const globals = Object.keys(window);
const overrides = 'let ' + globals.map(name => name + ' = null').join(',') + ';'
const userCode = 'alert("SPAM")';
try{
let result = new Function('', overrides + `return eval(${userCode})`);
console.log(result());
}catch(e){
console.error(e.message);
}
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论