diff --git a/php_v8js_macros.h b/php_v8js_macros.h index c43ad8f..1ae9938 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -205,6 +205,8 @@ struct php_v8js_ctx { std::vector accessor_list; char *tz; + + bool fatal_error_abort; #ifdef ZTS void ***zts_ctx; #endif diff --git a/v8js.cc b/v8js.cc index 5943fd6..a28cd5d 100644 --- a/v8js.cc +++ b/v8js.cc @@ -1134,6 +1134,10 @@ static PHP_METHOD(V8Js, executeString) php_v8js_timer_pop(TSRMLS_C); } + if(c->fatal_error_abort) { + zend_error(E_ERROR, "V8Js caught fatal error; message lost, sorry :-)"); + } + char exception_string[64]; if (c->time_limit_hit) { diff --git a/v8js_convert.cc b/v8js_convert.cc index 227ae2f..db8fa3c 100644 --- a/v8js_convert.cc +++ b/v8js_convert.cc @@ -30,6 +30,17 @@ extern "C" { #include #include + +jmp_buf *unwind_env; + +static void php_v8js_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args) +{ + longjmp(*unwind_env, 1); +} + + + + static void php_v8js_weak_object_callback(const v8::WeakCallbackData &data); /* Callback for PHP methods and functions */ @@ -43,6 +54,13 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct char *error; int error_len, i, flags = V8JS_FLAG_NONE; +#if PHP_V8_API_VERSION <= 3023008 + /* Until V8 3.23.8 Isolate could only take one external pointer. */ + php_v8js_ctx *ctx = (php_v8js_ctx *) isolate->GetData(); +#else + php_v8js_ctx *ctx = (php_v8js_ctx *) isolate->GetData(0); +#endif + /* Set parameter limits */ min_num_args = method_ptr->common.required_num_args; max_num_args = method_ptr->common.num_args; @@ -125,12 +143,34 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct fcc.called_scope = ce; fcc.object_ptr = value; - /* Call the method */ - zend_call_function(&fci, &fcc TSRMLS_CC); + jmp_buf env; + int val; + + void (*old_error_handler)(int, const char *, const uint, const char*, va_list); + old_error_handler = zend_error_cb; + zend_error_cb = php_v8js_error_handler; + + val = setjmp (env); + unwind_env = &env; + + if (val) { + ctx->fatal_error_abort = true; + zend_error_cb = old_error_handler; + } + else { + /* Call the method */ + zend_call_function(&fci, &fcc TSRMLS_CC); + } } isolate->Enter(); + if(ctx->fatal_error_abort) { + v8::V8::TerminateExecution(isolate); + info.GetReturnValue().Set(V8JS_NULL); + return; + } + failure: /* Cleanup */ if (argc) {