Domanda

It should be simple to create JavaScript intepreter in JavaScript using eval. I got this (using jQuery terminal):

term = $('#term_demo').terminal(function(command, term) {
    if (command !== '') {
        var result = window.eval("(" + command + ")");
        if (result !== undefined) {
            term.echo(String(result));
        }
    } else {
       term.echo('');
    }
}, {
    greetings: 'Javascript Interpreter',
    name: 'js_demo',
    height: 200,
    prompt: 'js> '
});

Demo

but it don't work when I execute function foo() { ... } the foo is not defined I need to use foo = function() { ... }. eval act like executed within (function() { <code> })(). Can it be there more complicated code that will not work too?

Is it possible to create a JavaScript interpreter using simple code without use the of js.js, that will work the same as browser console?

È stato utile?

Soluzione

I've created a bookmarklet which appends a kind of REPL in a page, designed for the major five browsers (Chrome 1+, IE 6+, Firefox 1+, Safari 3+, Opera 9+Can't remember the exacte version).
The core component, which evaluates the code is posted below, slightly modified + annotated.

/**
 * Evaluates some code in the global scope.
 * @param String code: Code to eval
 * @return Stringified result, prefixed with 'E:' if error.
 */
function globalEval(/*string*/ code) {
    var win = window, r, raw;
    try {
        if (win.execScript) { // eval in IE sucks, so use execScript instead
            r = win.$_$_$globalEval$_$_$ = {c:code};
            win.execScript('try{$_$_$globalEval$_$_$.r=eval($_$_$globalEval$_$_$.c);}catch(e){$_$_$globalEval$_$_$.e=e}');
            // /*Optional clean-up:*/ delete win.$_$_$globalEval$_$_$;
            if (r.e) throw r.e; // Error
            raw = r.r;
        } else {
            raw = win.eval(code);
        }
        r = '' + raw; // Stringify in the try-block
                      // It is possible that an error is thrown
                      // for example, for the following code: ({toString:1})
    } catch(err) {
        r = (err + ''); // Convert error to string
        // IE: If found, "[object" will be at index zero, which is falsy
        if (!r.indexOf('[object')) r = err.message;
        // r = 
        r = 'E:' + (raw=r);
    } finally {
        // raw = unmodified result (or Error instance)
        // FOR THIS EXAMPLE, raw is not used, and string r is returned
        return /*string*/ r;
    }
}

I've implemented the functionality in a form, which contains several controls including an input+output textarea.

Note: The code is evaluated in the global context. And such, any variables in code will be leaked to the global scope. For an interpreter, you could use an iframe to create a new scope (and modify var win in my function).

var win = frames['name_of_frame'], ... // or
var win = frame_DOM_element.contentWindow, ...

Altri suggerimenti

The parenthesis you're appending around your incoming command produces illegal syntax. You should wrap it with an anonymous self-executing function instead.

Example: http://jsfiddle.net/bW6Fv/1/

var command = "function foo(x){return x+x;} alert(foo(10));";

window.eval("!function(){" + command + "}()");​

EDIT

If you want your evaluated scripts to be available globally, you'll have to leave them unwrapped or explicitly assign values to the global window object.

Example: http://jsfiddle.net/bW6Fv/2/

var command = "window.foo = function(x){return x+x;}; alert(foo(10));";

window.eval("!function(){ " + command + "}();");
window.eval("alert(foo(20));");

command = "function bar(x){return x / 2;}; alert(bar(10));";

window.eval(command);
window.eval("alert(bar(20));");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top