77using namespace v8 ;
88using namespace node ;
99
10+ Persistent<FunctionTemplate> node::Context::constructor_template;
11+
12+ void
13+ node::Context::Initialize (Handle<Object> target)
14+ {
15+ HandleScope scope;
16+
17+ Local<FunctionTemplate> t = FunctionTemplate::New (node::Context::New);
18+ constructor_template = Persistent<FunctionTemplate>::New (t);
19+ constructor_template->InstanceTemplate ()->SetInternalFieldCount (1 );
20+ constructor_template->SetClassName (String::NewSymbol (" Context" ));
21+
22+ target->Set (String::NewSymbol (" Context" ), constructor_template->GetFunction ());
23+ }
24+
25+ Handle<Value>
26+ node::Context::New (const Arguments& args)
27+ {
28+ HandleScope scope;
29+
30+ node::Context *t = new node::Context ();
31+ t->Wrap (args.This ());
32+
33+ return args.This ();
34+ }
35+
36+ node::Context::~Context () {
37+ _context.Dispose ();
38+ }
39+
40+ Local<Object>
41+ node::Context::NewInstance ()
42+ {
43+ Local<Object> context = constructor_template->GetFunction ()->NewInstance ();
44+ node::Context *nContext = ObjectWrap::Unwrap<node::Context>(context);
45+ nContext->_context = v8::Context::New ();
46+ return context;
47+ }
48+
49+ v8::Persistent<v8::Context>
50+ node::Context::GetV8Context ()
51+ {
52+ return _context;
53+ }
54+
55+
1056Persistent<FunctionTemplate> node::Script::constructor_template;
1157
1258void
@@ -19,8 +65,12 @@ node::Script::Initialize (Handle<Object> target)
1965 constructor_template->InstanceTemplate ()->SetInternalFieldCount (1 );
2066 constructor_template->SetClassName (String::NewSymbol (" Script" ));
2167
68+ NODE_SET_PROTOTYPE_METHOD (constructor_template, " createContext" , node::Script::CreateContext);
69+ NODE_SET_PROTOTYPE_METHOD (constructor_template, " runInContext" , node::Script::RunInContext);
2270 NODE_SET_PROTOTYPE_METHOD (constructor_template, " runInThisContext" , node::Script::RunInThisContext);
2371 NODE_SET_PROTOTYPE_METHOD (constructor_template, " runInNewContext" , node::Script::RunInNewContext);
72+ NODE_SET_METHOD (constructor_template, " createContext" , node::Script::CreateContext);
73+ NODE_SET_METHOD (constructor_template, " runInContext" , node::Script::CompileRunInContext);
2474 NODE_SET_METHOD (constructor_template, " runInThisContext" , node::Script::CompileRunInThisContext);
2575 NODE_SET_METHOD (constructor_template, " runInNewContext" , node::Script::CompileRunInNewContext);
2676
@@ -44,6 +94,37 @@ node::Script::~Script() {
4494}
4595
4696
97+ Handle<Value>
98+ node::Script::CreateContext (const Arguments& args)
99+ {
100+ HandleScope scope;
101+
102+ Local<v8::Object> context = node::Context::NewInstance ();
103+
104+ if (args.Length () > 0 ) {
105+
106+ Local<Object> sandbox = args[0 ]->ToObject ();
107+ Local<Array> keys = sandbox->GetPropertyNames ();
108+
109+ for (int i = 0 ; i < keys->Length (); i++) {
110+ Handle<String> key = keys->Get (Integer::New (i))->ToString ();
111+ Handle<Value> value = sandbox->Get (key);
112+ context->Set (key, value);
113+ }
114+ }
115+
116+
117+ return scope.Close (context);
118+ }
119+
120+ Handle<Value>
121+ node::Script::RunInContext (const Arguments& args)
122+ {
123+ return
124+ node::Script::EvalMachine<unwrapExternal, userContext, returnResult>(args);
125+ }
126+
127+
47128Handle<Value>
48129node::Script::RunInThisContext (const Arguments& args)
49130{
@@ -59,6 +140,14 @@ node::Script::RunInNewContext(const Arguments& args) {
59140}
60141
61142
143+ Handle<Value>
144+ node::Script::CompileRunInContext (const Arguments& args)
145+ {
146+ return
147+ node::Script::EvalMachine<compileCode, userContext, returnResult>(args);
148+ }
149+
150+
62151Handle<Value>
63152node::Script::CompileRunInThisContext (const Arguments& args)
64153{
@@ -91,29 +180,50 @@ Handle<Value> node::Script::EvalMachine(const Arguments& args) {
91180 ));
92181 }
93182
183+ const int sbIndex = iFlag == compileCode ? 1 : 0 ;
184+ if (cFlag == userContext && args.Length () < (sbIndex + 1 )) {
185+ return ThrowException (Exception::TypeError (
186+ String::New (" needs a 'context' argument." )
187+ ));
188+ }
189+
190+
94191 Local<String> code;
95192 if (iFlag == compileCode) { code = args[0 ]->ToString (); }
96193
97194 Local<Object> sandbox;
98- const int sbIndex = iFlag == compileCode ? 1 : 0 ;
99195 if (cFlag == newContext) {
100196 sandbox = args.Length () > sbIndex ? args[sbIndex]->ToObject () : Object::New ();
101197 }
198+ else if (cFlag == userContext) {
199+ sandbox = args[sbIndex]->ToObject ();
200+ }
102201 const int fnIndex = sbIndex + (cFlag == newContext ? 1 : 0 );
103202 Local<String> filename = args.Length () > fnIndex ? args[fnIndex]->ToString ()
104203 : String::New (" evalmachine.<anonymous>" );
105204
106- Persistent<Context> context;
205+ Persistent<v8:: Context> context;
107206 Local<Array> keys;
108207 unsigned int i;
109208 if (cFlag == newContext) {
110209 // Create the new context
111- context = Context::New ();
210+ context = v8:: Context::New ();
112211
113- // Enter and compile script
212+ } else if (cFlag == userContext) {
213+ // Use the passed in context
214+ Local<Object> contextArg = args[sbIndex]->ToObject ();
215+ node::Context *nContext = ObjectWrap::Unwrap<node::Context>(sandbox);
216+ context = nContext->GetV8Context ();
217+ }
218+
219+ // New and user context share code. DRY it up.
220+ if (cFlag == userContext || cFlag == newContext) {
221+
222+ // Enter the context
114223 context->Enter ();
115224
116- // Copy objects from global context, to our brand new context
225+ // Copy everything from the passed in sandbox (either the persistent
226+ // context for runInContext(), or the sandbox arg to runInNewContext()).
117227 keys = sandbox->GetPropertyNames ();
118228
119229 for (i = 0 ; i < keys->Length (); i++) {
@@ -167,7 +277,7 @@ Handle<Value> node::Script::EvalMachine(const Arguments& args) {
167277 }
168278 if (result.IsEmpty ()) {
169279 return try_catch.ReThrow ();
170- } else if (cFlag == newContext) {
280+ } else if (cFlag == userContext || cFlag == newContext) {
171281 // success! copy changes back onto the sandbox object.
172282 keys = context->Global ()->GetPropertyNames ();
173283 for (i = 0 ; i < keys->Length (); i++) {
@@ -183,6 +293,9 @@ Handle<Value> node::Script::EvalMachine(const Arguments& args) {
183293 context->DetachGlobal ();
184294 context->Exit ();
185295 context.Dispose ();
296+ } else if (cFlag == userContext) {
297+ // Exit the passed in context.
298+ context->Exit ();
186299 }
187300
188301 return result == args.This () ? result : scope.Close (result);
0 commit comments