2121
2222#include " node.h"
2323#include " node_script.h"
24+ #include " node_watchdog.h"
2425#include < assert.h>
2526
2627namespace node {
@@ -42,6 +43,7 @@ using v8::Persistent;
4243using v8::Integer;
4344using v8::Function;
4445using v8::FunctionTemplate;
46+ using v8::V8;
4547
4648
4749class WrappedContext : ObjectWrap {
@@ -74,10 +76,12 @@ class WrappedScript : ObjectWrap {
7476 enum EvalInputFlags { compileCode, unwrapExternal };
7577 enum EvalContextFlags { thisContext, newContext, userContext };
7678 enum EvalOutputFlags { returnResult, wrapExternal };
79+ enum EvalTimeoutFlags { noTimeout, useTimeout };
7780
7881 template <EvalInputFlags input_flag,
7982 EvalContextFlags context_flag,
80- EvalOutputFlags output_flag>
83+ EvalOutputFlags output_flag,
84+ EvalTimeoutFlags timeout_flag>
8185 static Handle<Value> EvalMachine (const Arguments& args);
8286
8387 protected:
@@ -243,7 +247,8 @@ Handle<Value> WrappedScript::New(const Arguments& args) {
243247 t->Wrap (args.This ());
244248
245249 return
246- WrappedScript::EvalMachine<compileCode, thisContext, wrapExternal>(args);
250+ WrappedScript::EvalMachine<
251+ compileCode, thisContext, wrapExternal, noTimeout>(args);
247252}
248253
249254
@@ -275,43 +280,50 @@ Handle<Value> WrappedScript::CreateContext(const Arguments& args) {
275280
276281Handle<Value> WrappedScript::RunInContext (const Arguments& args) {
277282 return
278- WrappedScript::EvalMachine<unwrapExternal, userContext, returnResult>(args);
283+ WrappedScript::EvalMachine<
284+ unwrapExternal, userContext, returnResult, useTimeout>(args);
279285}
280286
281287
282288Handle<Value> WrappedScript::RunInThisContext (const Arguments& args) {
283289 return
284- WrappedScript::EvalMachine<unwrapExternal, thisContext, returnResult>(args);
290+ WrappedScript::EvalMachine<
291+ unwrapExternal, thisContext, returnResult, useTimeout>(args);
285292}
286293
287294
288295Handle<Value> WrappedScript::RunInNewContext (const Arguments& args) {
289296 return
290- WrappedScript::EvalMachine<unwrapExternal, newContext, returnResult>(args);
297+ WrappedScript::EvalMachine<
298+ unwrapExternal, newContext, returnResult, useTimeout>(args);
291299}
292300
293301
294302Handle<Value> WrappedScript::CompileRunInContext (const Arguments& args) {
295303 return
296- WrappedScript::EvalMachine<compileCode, userContext, returnResult>(args);
304+ WrappedScript::EvalMachine<
305+ compileCode, userContext, returnResult, useTimeout>(args);
297306}
298307
299308
300309Handle<Value> WrappedScript::CompileRunInThisContext (const Arguments& args) {
301310 return
302- WrappedScript::EvalMachine<compileCode, thisContext, returnResult>(args);
311+ WrappedScript::EvalMachine<
312+ compileCode, thisContext, returnResult, useTimeout>(args);
303313}
304314
305315
306316Handle<Value> WrappedScript::CompileRunInNewContext (const Arguments& args) {
307317 return
308- WrappedScript::EvalMachine<compileCode, newContext, returnResult>(args);
318+ WrappedScript::EvalMachine<
319+ compileCode, newContext, returnResult, useTimeout>(args);
309320}
310321
311322
312323template <WrappedScript::EvalInputFlags input_flag,
313324 WrappedScript::EvalContextFlags context_flag,
314- WrappedScript::EvalOutputFlags output_flag>
325+ WrappedScript::EvalOutputFlags output_flag,
326+ WrappedScript::EvalTimeoutFlags timeout_flag>
315327Handle<Value> WrappedScript::EvalMachine (const Arguments& args) {
316328 HandleScope scope (node_isolate);
317329
@@ -346,7 +358,18 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
346358 ? args[filename_index]->ToString ()
347359 : String::New (" evalmachine.<anonymous>" );
348360
349- const int display_error_index = args.Length () - 1 ;
361+ uint64_t timeout = 0 ;
362+ const int timeout_index = filename_index + 1 ;
363+ if (timeout_flag == useTimeout && args.Length () > timeout_index) {
364+ if (!args[timeout_index]->IsUint32 ()) {
365+ return ThrowException (Exception::TypeError (
366+ String::New (" needs an unsigned integer 'ms' argument." )));
367+ }
368+ timeout = args[timeout_index]->Uint32Value ();
369+ }
370+
371+ const int display_error_index = timeout_index +
372+ (timeout_flag == noTimeout ? 0 : 1 );
350373 bool display_error = false ;
351374 if (args.Length () > display_error_index &&
352375 args[display_error_index]->IsBoolean () &&
@@ -416,7 +439,17 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
416439
417440
418441 if (output_flag == returnResult) {
419- result = script->Run ();
442+ if (timeout) {
443+ Watchdog wd (timeout);
444+ result = script->Run ();
445+ } else {
446+ result = script->Run ();
447+ }
448+ if (try_catch.HasCaught () && try_catch.HasTerminated ()) {
449+ V8::CancelTerminateExecution (args.GetIsolate ());
450+ return ThrowException (Exception::Error (
451+ String::New (" Script execution timed out." )));
452+ }
420453 if (result.IsEmpty ()) {
421454 if (display_error) DisplayExceptionLine (try_catch);
422455 return try_catch.ReThrow ();
0 commit comments