Reputation: 2321
Here is my code:
<div class="row">
<div class="col-md-4 black">
<% @unit.attempts.order("created_at DESC").each do |attempt| %>
<p><%= attempt.body %></p>
<% end %>
</div>
<div class="col-md-4 run">
<div class="view-lines">
<h2>app.js</h2>
<%= form_for [@unit, @attempt] do |f| %>
<%= f.text_area :body,class: "editor"%>
<%= f.submit "Run"%>
<% end %>
<script>
$(document).ready(function(){
var code = $(".editor")[0];
var editor = CodeMirror.fromTextArea(code,{
lineNumbers: true,
styleActiveLine: true,
mode: "javascript",
matchBrackets: true
})
$('.view-lines').each(function(index,item) {
var v= $(item).find('.editor').val();
alert(eval(v));
});
})
</script>
For example if I want to add inside the text area
var favoriteFood = 'pizza';
console.log(favoriteFood);
The result I got in the alert
var favoriteFood = 'pizza';
console.log(favoriteFood);
I want to run the javascript code in my example in the alert it should be pizza
Upvotes: 0
Views: 114
Reputation: 1012
You're not understanding what eval()
does.
The eval
takes as input the expression and returns the value of the last expression:
console.log(eval("2+2")) // -> 4
console.log(eval("Math.pow(2, 10)")) // -> 1024
console.log(eval("let x = 100; x - 1")) // -> 99
console.log()
is not changed inside the eval()
. It does the same as in the normal code.
console.log()
?You can redefine console
and console.log()
:
function executeCode(code) {
let logs = []; // Logs array
// Redefine console
let console = {
log(...args) { // We can pass as many args as we want
logs.push(args);
}
}
// Eval the code
eval(code);
// Return the logs
return logs;
}
// Demos
console.log(executeCode('console.log("Hello, world!")'))
console.log(executeCode('let x = 5; console.log("X is", x)'))
eval
is evillet password = "1234"; // An important variable
let login = "vasya" // Another one
// Execute code
function executeCode(code) {
let logs = []; // Logs array
// Redefine console
let console = {
log(...args) { // We can pass as many args as we want
logs.push(args);
}
}
// Eval the code
eval(code);
// Return the logs
return logs;
}
// Code may be not yours, as example shared to you
console.log(executeCode('console.log("Got your password: ", password)')) // Code can access to almost anything
console.log(executeCode('login = "abcdef"')) // And can modify everything
console.log("INFO: Login is", login)
// Or it can redirect you
// console.log(executeCode('window.location.href = "example.com"'))
Of course there are some ways to secure this, and if you want — I can add them
Upvotes: 0
Reputation: 1922
I'm not sure what you're trying to accomplish here, but for the purpose of just solving your problem, you could evaluate the commands first assuming that they populate a given variable name, and then alert using that variable name instead of the result of eval
. So in your case, something like this might work:
eval("var favoriteFood='pizza';");
alert(favoriteFood); // will alert with the message "pizza"
If your expectation is that a user would put a separate command on each line you could loop through the lines and evaluate them all separately, like this:
eval("var favoriteFood='pizza';");
eval("favoriteFood += ' slices';");
alert(favoriteFood); // will alert with the message "pizza slices"
Overall you should never blindly execute user input data like this, it's a big problem from a security perspective. But I hope this helps with whatever you're cooking up today.
Edit : (responding to comment question)
In your case, instead of this:
alert(eval(v));
You could do this:
eval(v);
alert(favoriteFood);
Again this assumes that in your text area, you are setting a variable named favoriteFood
. If you want to remove that qualification I don't think there's a way you can do this with eval
.
Upvotes: 0