6

How do I manage it to place variables and run code inside Sandbox() through Run()?

function Sandbox() {
    this.test = 'insandbox';
}

Sandbox.prototype.Run = function(src) {
    eval.call(this, src);
};

Sandbox.prototype.getvar = function(name) {
    return this[name];
};

var bx = new Sandbox();
bx.Run('var x = 1;');
print(bx.getvar('test'))
print(bx.getvar('x'))        // undefined
print(x)

Please no answers regarding eval() is insecure and I shouldn't use it. Please no answers regarding the use of setters/getters.

Thanks for reading!

1
  • I think you're in the wrong scope Commented Aug 11, 2011 at 1:38

3 Answers 3

3

This might not be what you're looking for but what if instead of passing a string to your sandbox you pass a function. This even allows the possibility of using eval for source files.

Your code would work like this:

...

Sandbox.prototype.Run = function(fn){
    fn.call(this);
}

var bx = new Sandbox();
bx.run(function(){
    this.x = 1;
});
bx.getVar("x") // 1

then if you wanted to use eval all you would have to is write a function to append the function syntax

/* source.js */
this.x = 1;
this.blah = "Hello, World!";

With:

Sandbox.prototype.evaluate = function(src){
     return eval("function(){" + src + "}");
}

bx.Run(Sandbox.evaluate(src));
bx.getVar("x") // 1
bx.getVar("blah") // "Hello, World!"

Also with this method you can pass the sand-boxed code objects and functions to use by passing them to the function which will simulate an entirely new pseudo-environment to work with.

Edit: I did a little research on the perfect answer to your question which is

Can I iterate over the variables declared in a local scope?

And the answer is no (StackOverflow). It looks like it's a limitation of javascript at the moment. Hopefully something like this will emerge in the new spec.

My idea at the moment would be to eval the source to make all the var statements go to the window object which, with some effort, could be iterated over and added to the Sandbox object manually.

Like this Warning: horribly simplified

(function(){
    var src = get_source_file();
    eval(src);
    iterate_over_each_newly_created_window_property(function(property, value){
         bx[property] = value;
         window[property] = undefined;
    });
})();

Edit 2: MY IDEA WORKS =)

function Sandbox(){
    return this;
}
Sandbox.prototype.run = function(src){
    // Take a snapshopt of the window object before
    var before = {};
    var prop;
    for(prop in window){
        before[prop] = true;
    }
    // Then evaluate the source
    window.eval(src);
    // Then see what changed
    var changed = [];
    for(prop in window){
        if(!before[prop]){
            // Add to the sandbox object
            this[prop] = window[prop];
            delete window[prop];
        }
    }
}
var bx = new Sandbox();
bx.run("var x = 'Hello, World!';");
alert(bx.x);

A working example (jsFiddle)

function Sandbox(){
this.keys = [];
this.values = [];
    return this;
}
Sandbox.prototype.eval = function(src){
    var before = {}, prop, fn;
    // Take a snapshopt of the window object before
    src = "function(" + this.keys.join(",") + "){" + src + "}";
    src = src.replace(/var/g, "");
    /* I'm not a wisard at regex so a better one should be used avoid this bug
    var x, y, z; */
    for(prop in window){
        before[prop] = true;
    }
    // Then evaluate the source
    fn = window.eval(src);
    fn.apply(window, this.values);
    // Then see what changed
    for(prop in window){
        if(!before[prop]){
            // Add to the sandbox object
            this.keys.push(prop);
            this.values.push(window[prop]);
            this[prop] = window[prop];
            delete window[prop];
        }
    }
}
var bx = new Sandbox();
bx.eval("var x = 1;");
bx.eval("var y = x;");
alert(bx.x);
alert(bx.y);

Edit 3: Fixed bug to your specifications

Now I know there are bugs in it and some functions that might make it go haywire. Now it's your job to clean up the code for real use. I gave you conceptually how it can be done.

Sign up to request clarification or add additional context in comments.

3 Comments

This is not what I can use in my situation but thanks for your support!
No, those variables should be placed inside the Sandbox object.
This is not that bad! :-) I was just thinking about using with() for that purpose. I will def. look over that approach, perhaps we can fine tune it a bit more. I do not like that window.eval() ;-)
2

This should work:

...

Sandbox.prototype.run = function(src) {
    eval(src);
};

...

bx.run('this.x = 1;');

...

5 Comments

bx.getvar('x') will result in undefined. i would like not to need the use 'this' in the expression for Run().
You need to use this if you want it to work. var creates a local variable that's not associated with the instance of Sandbox.
Yes this works. Thank you. But I can not add this to every expression because I don't know what exact kind of expression is used every time for Run().
But isn't it possible to set a local variable and use getvar() to return the local variable?
No, the local variable is gone as soon as its scope ends. And that scope is not part of the getvar method.
1

you could use a closure

Sandbox.prototype.Run = function(src) {
    (function(_src){
        eval.call(this, _src);
    })(src);
};

1 Comment

eval can only run in the global scope. That's a javascript limitation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.