On Mar 2, 9:18 am, Alex Iskander <[email protected]> wrote:
> You may be able to use this to call Context::New(0, GlobalTemplate,
> GlobalObject);
>
> Where GlobalObject is the object passed to evalcx.
Thanks, Alex.
That seems to do two things:
1. the code executes in a new context with no globals.
2. the object passed to evalcx is set to null. (!?)
Here's my code:
// the c++ function
static v8::Handle<v8::Value> EvalCX (const v8::Arguments& args)
{
v8::HandleScope handlescope;
v8::String::Utf8Value code(args[0]);
v8::Local<v8::Object> sandbox = args[1]->ToObject();
v8::Handle<v8::String> source = v8::String::New(*code);
// Create a new execution environment for sandbox
// problem here.
v8::Handle<v8::Context> context = v8::Context::New(NULL,
Handle<ObjectTemplate>(), sandbox);
// Enter the newly created execution environment.
v8::Context::Scope context_scope(context);
v8::Handle<v8::Script> script = v8::Script::Compile(source,
v8::String::New("evalcx"));
if (script.IsEmpty()) return v8::ThrowException(v8::String::New
("Error parsing script"));
// destroys the sandbox object!?
v8::Handle<v8::Value> result = script->Run();
if (result.IsEmpty()) return v8::ThrowException(v8::String::New
("Error running script"));
return result;
}
// the binding to global in main()
global->Set(v8::String::New("evalcx"), v8::FunctionTemplate::New
(EvalCX)->GetFunction());
// the js
code = "foo = 1; bar = 2;";
foo = 2;
o = { foo : 0 };
evalcx(code, obj);
print( o.foo ); // expected: 1. actual: error, o is null
print( o.bar ); // expected: 2. actual: error, o is null
print( foo ); // expected: 2. actual: 2
print( bar ); // expected: undefined. actual: undefined
So, it looks like it's taking the code out of the caller's global
context, and putting it into a new context. That's great. However,
it's also destroying the object that gets passed in, rather than
modifying it.
>
> However, it may not work; I'm not certain what would happen if you
> pass an object belonging to another context as a global object of a
> new context.
>
> So, plan B might be to manually copy the items from your global object
> passed to evalcx to the global object for your new context.
>
> I hope that helps,
>
> Alex
>
> On Mar 2, 2009, at 11:05 AM, Isaac Z. Schlueter wrote:
>
>
>
>
>
> > Thanks, Stephan.
>
> > It looks like what you're doing will execute the code and set "this"
> > to the object in question.
>
> > However, what I'd really like to do is execute code and set a given
> > object as the global scope. Here's an example with some code:
>
> > var code = "var foo = 'bar';";
> > var obj = { foo : "baz" };
> > evalcx( code, obj ); // execute code using "obj" as the global object
> > print( obj.foo ); // prints "bar"
>
> > Unless I'm misreading your example, what you're describing will work
> > in this case:
>
> > var code = "this.foo = 'bar';";
> > var obj = { foo : "baz" };
>
> > But, I can already do that from JS like so:
>
> > (new Function(code)).call(obj);
>
> > If I could eval code in an arbitrary global scope within Javascript,
> > which did not have any access to the global scope, then it would be
> > possible to implement a capability-based security model.
>
> > Also, it would make it possible to load and execute many different
> > scripts in a row without having to "clean up" the globals that each
> > one might create. After being evaluated, the temporary global scope
> > could be discarded, and would be garbage collected normally.
>
> > For example, let's say you have a fastcgi handler written in
> > Javascript, which reads and evals the SCRIPT_FILENAME file. The
> > problem is that, since the evaled code shares a global scope with the
> > fcgi handler, it also shares a global scope with *every other script
> > loaded by that handler.* That means that every global variable is
> > persistent in memory, and only gets garbage collected when you restart
> > the server. Not ideal! :)
>
> > --
> > Isaac Z. Schlueter
>
> > On Mar 1, 5:06 pm, Stephan Beal <[email protected]> wrote:
> >> On Mar 2, 1:34 am, "Isaac Z. Schlueter" <[email protected]> wrote:
>
> >>> I'm trying to write a function that will execute a bit of Javascript
> >>> within an arbitrary global scope. Something like the "evalcx"
> >>> function in the Spidermonkey shell.
>
> >>> I've got a function defined and exposed to the Javascript that takes
> >>> an object as an argument, and stores it as a Handle<Object>.
> >>> However,
> >>> in order to create a new execution context, I need a
> >>> Handle<ObjectTemplate>.
>
> >> Do you need a new Context, or just an object to eval the code in? If
> >> you just need an Object to execute the code in...
>
> >> They way i ended up doing this was getting the 'eval' function from
> >> my
> >> local object, then using Call() on that Function object:
>
> >> TryCatch tryer;
> >> Local<Value> rv;
> >> Local<Function> eval = Function::Cast( *(db->jsobj-
> >> >Get(String::New
> >> ("eval"))) );
> >> // ^^^^^ db->jsobj is my context object
> >> for( int i = 0; i < argc; ++i )
> >> {
> >> char const * cp = reinterpret_cast<char const *>
> >> ( sqlite3_value_text( argv[i] ) );
> >> if( ! cp || !*cp ) continue;
> >> Local<Value> arg = String::New( cp,
> >> sqlite3_value_bytes( argv
> >> [i] ) );
> >> rv = eval->Call( db->jsobj, 1, &arg );
> >> // ^^^^ that will, in theory, eval the code in the context of db-
> >> >jsobj
>
> >> if( rv.IsEmpty() )
> >> {
> >> std::string
> >> err( CastFromJS<std::string>( tryer.Exception() ) );
> >> sqlite3_result_text( context, err.c_str(),
> >> static_cast<int>(err.size
> >> ()), SQLITE_TRANSIENT );
> >> return;
> >> }
> >> }
>
> Alex Iskander
> Web and Marketing
> TPSi
--~--~---------~--~----~------------~-------~--~----~
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
-~----------~----~----~----~------~----~------~--~---