diff --git a/php_v8js_macros.h b/php_v8js_macros.h index 7fbcd1d..61f30c6 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -83,6 +83,7 @@ extern "C" { /* Options */ #define V8JS_FLAG_NONE (1<<0) #define V8JS_FLAG_FORCE_ARRAY (1<<1) +#define V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS (1<<2) #define V8JS_DEBUG_AUTO_BREAK_NEVER 0 #define V8JS_DEBUG_AUTO_BREAK_ONCE 1 diff --git a/tests/php_exceptions_003.phpt b/tests/php_exceptions_003.phpt new file mode 100644 index 0000000..6bf71a4 --- /dev/null +++ b/tests/php_exceptions_003.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test V8::executeString() : PHP Exception handling (basic JS propagation) +--SKIPIF-- + +--FILE-- +foo = new \Foo(); + +$JS = <<< EOT +try { + PHP.foo.throwException(); + // the exception should abort further execution, + // hence the print must not pop up + print("after throwException\\n"); +} catch(e) { + print("JS caught exception!\\n"); + var_dump(e.getMessage()); +} +EOT; + +$v8->executeString($JS, 'php_exceptions_003', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); + +?> +===EOF=== +--EXPECTF-- +JS caught exception! +string(14) "Test-Exception" +===EOF=== diff --git a/v8js_class.cc b/v8js_class.cc index 3c25442..d242049 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -1078,6 +1078,7 @@ PHP_MINIT_FUNCTION(v8js_class) /* {{{ */ zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("FLAG_NONE"), V8JS_FLAG_NONE TSRMLS_CC); zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("FLAG_FORCE_ARRAY"), V8JS_FLAG_FORCE_ARRAY TSRMLS_CC); + zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("FLAG_PROPAGATE_PHP_EXCEPTIONS"), V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS TSRMLS_CC); #ifdef ENABLE_DEBUGGER_SUPPORT zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("DEBUG_AUTO_BREAK_NEVER"), V8JS_DEBUG_AUTO_BREAK_NEVER TSRMLS_CC); diff --git a/v8js_object_export.cc b/v8js_object_export.cc index 218e566..ec11263 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -21,6 +21,7 @@ extern "C" { #include "ext/standard/php_string.h" #include "zend_interfaces.h" #include "zend_closures.h" +#include "zend_exceptions.h" } #include "php_v8js_macros.h" @@ -33,7 +34,7 @@ static void v8js_weak_object_callback(const v8::WeakCallbackData& info TSRMLS_DC) /* {{{ */ { - v8::Handle return_value; + v8::Handle return_value = V8JS_NULL; zend_fcall_info fci; zend_fcall_info_cache fcc; zval fname, *retval_ptr = NULL, **argv = NULL; @@ -138,10 +139,6 @@ static void v8js_call_php_func(zval *value, zend_class_entry *ce, zend_function } zend_end_try(); - if(EG(exception)) { - v8js_terminate_execution(isolate); - } - failure: /* Cleanup */ if (argc) { @@ -152,11 +149,19 @@ failure: efree(fci.params); } - if (retval_ptr != NULL) { + if(EG(exception)) { + if(ctx->flags & V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS) { + return_value = isolate->ThrowException(zval_to_v8js(EG(exception), isolate TSRMLS_CC)); + zend_clear_exception(TSRMLS_C); + } else { + v8js_terminate_execution(isolate); + } + } else if (retval_ptr != NULL) { return_value = zval_to_v8js(retval_ptr, isolate TSRMLS_CC); + } + + if (retval_ptr != NULL) { zval_ptr_dtor(&retval_ptr); - } else { - return_value = V8JS_NULL; } info.GetReturnValue().Set(return_value);