1

I'm evaluating scripts in Ruby, and I'd like each script to have it's own sandbox with a global variable called $window. The $window variable should point to something different depending on which sandbox the script is running in. A thread-local variable would work, but I'm not using threads. I'm using the Ruby C API, so that opens the possibilities a bit.

Right now, I run each script within a Binding, so they are somewhat sandboxed there. A binding can have closed local variables, but not globals. Here's the idea:

sandbox1 = window1.get_binding
sandbox2 = window2.get_binding
sandbox3 = window3.get_binding

sandbox1.eval('$window.foo') # calls 'foo' on window 1
sandbox2.eval('$window.foo') # calls 'foo' on window 2
sandbox3.eval('$window.foo') # calls 'foo' on window 3

Is there any way to close a global variable within a Binding? I found a possible solution and posted it below.

6
  • It sounds like you're worried about synchronizing the access of several threads to a global? Commented Dec 21, 2012 at 6:35
  • They're not in separate threads, although that would make it easy! They're different windows in a web browser. Commented Dec 21, 2012 at 16:09
  • What is the underlying goal you are trying to accomplish? Global variables are generally considered a bad practice. Commented Dec 21, 2012 at 16:28
  • I clarified my question. I want to have multiple sandboxes with global variables of the same name. Commented Dec 23, 2012 at 20:40
  • Why was this tagged javascript and webkit? Commented Dec 23, 2012 at 20:42

2 Answers 2

1

What will be the different windows be tied to ?

If they're bound to a Thread, then the easiest way to solve your problem is to have a Thread local variable, if is bound to something else (let's say current time), then you might want to use a global hash.

I would personnally go for a dedicated class which will make it easier to refactor later (you will probably refactor this since globals are a code smell for poor dependency injection ) :

class Windows < Hash
end
WINDOWS = Windows.new
...
window_scope = WINDOWS[Time.now].binding

then you have a mutable constant which is actually a global collection.

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

1 Comment

Sadly, they're not bound to threads, but using a global hash of some sort might work. I'll edit the main post with some clarification.
0

I found a possible solution using the Ruby C API. Anything that's evaluated within a binding will be somewhere under the call frame of that binding. Using Ruby 1.8.7, I can do this in C:

public VALUE getCurrentWindow()
{
    // Get the current call frame from Ruby.
    FRAME* frame = ruby_frame;

    // Traverse up the call frame stack until we find a Window class.
    while (frame) {
        if (RTEST(rb_obj_is_kind_of(frame->self, rb_cWindow))
            return frame->self;

        frame = frame->prev;
    }

    // Couldn't find the window.
    return Qnil;
}

It seems to work, but we'll see if I run into problems.

Comments

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.