0

My goal is to write a javascript application that will take text as an input and compile/run that text as code.

For example, say the JS application has a light that can turn red or green. The user inputted text could be lightRed(); to turn it red, and lightGreen(); to turn it green. I think the standard way to solve this kind of issue is to implement some kind of lexer/parser, like what Jison does.

However, I'm fairly new to JS programming and that seems like a daunting task - especially when I later plan to add more complex functionality to it like if/else statements. So I was wondering if it was possible to have the inputted text treated as javascript, essentially using the browser's ability to process javascript. So the javascript application will have a light, and it will have functions called lightRed() and lightGreen(). Text inputted to the javascript will be treated as javascript, so writing lightRed() as text will directly execute the lightRed() function in the application. Is this possible? Would this be more complicated than just using something like Jison? Thanks!

user2461391
  • 1,433
  • 3
  • 16
  • 26

2 Answers2

6

The easiest way to compile the inputted JavaScript would be to use the eval function. This will evaluate and execute any code passed in as a string.

Example:

eval(document.getElementById('code').value)

JSFiddle

Be aware though that this does give the user the potential to execute any code that he wants without restriction, so think carefully before allowing this.

To help mitigate any security risk, you could execute the code in the global scope, as shown in this answer, preventing the code from accessing any of your local variables, and this would be just like if the user ran the code from their browser's developer console.

More Secure Example:

(function(){eval.apply(this,[document.getElementById('code').value])})()

More Secure JSFiddle

Community
  • 1
  • 1
Joshua Dwire
  • 5,415
  • 5
  • 29
  • 50
1

eval() will evaluate a string expression as JavaScript. Most people (including myself) will warn you about security holes; but if you think about it, the user could open up the javascript console and type and run all the same code.. So go for it :)

asifrc
  • 5,781
  • 2
  • 18
  • 22
  • 2
    It's not the same as if they opened up the console and typed. Say you had all your code in an IIFE (`(function () { /* Code here */ }());`). You wouldn't be able to access it from the console. But using `eval`, code is executed in the current scope, so it *can* access that local stuff in the IIFE. Just food for thought – Ian Aug 09 '13 at 16:32
  • @Ian I was not aware of that, interesting.. Do you have any articles/docs that go in depth about this? – asifrc Aug 09 '13 at 16:35
  • @Ian You wouldn't be able to access that from the *console*, but Chrome Developer Tools, for example, still lets you examine and alter variables in a function's local scope. – Trevor Dixon Aug 09 '13 at 16:37
  • @TrevorDixon wait.. Chrome Developer Tools (ctrl+shift+j) isn't the console?? What then is the _console_ ?? – asifrc Aug 09 '13 at 16:39
  • 1
    You've got the Console tab (which is what I was referring to by "the console"), but there's also the Sources tab which allows you to mess with local variables. You can even edit the source of a javascript file there and have Chrome execute the modified version. – Trevor Dixon Aug 09 '13 at 16:43
  • @asifrc Not really. It's just the way `eval` and IIFEs work. `eval` executes in the current scope. And IIFEs create a scope that isn't accessible outside of it (like any local scope). You can read about them here: http://en.wikipedia.org/wiki/Immediately-invoked_function_expression – Ian Aug 09 '13 at 16:51
  • @TrevorDixon Great point, I didn't think of that. Mainly because I never use that section of Developer Tools. I wasn't trying to argue against this answer's real point, I just wanted to point out how you could've gotten around letting them type in the `console` (which is still true), but doesn't prohibit what you're talking about :) – Ian Aug 09 '13 at 16:52