0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-12-22 10:31:53 +00:00

Allow PHP exception to JS propagation

This commit is contained in:
Stefan Siegl 2015-08-22 15:16:02 +02:00
parent f7a592052f
commit 462eb623b3
4 changed files with 51 additions and 8 deletions

View File

@ -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

View File

@ -0,0 +1,36 @@
--TEST--
Test V8::executeString() : PHP Exception handling (basic JS propagation)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function throwException() {
throw new \Exception("Test-Exception");
}
}
$v8 = new V8Js();
$v8->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===

View File

@ -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);

View File

@ -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<v8::Object, zva
/* Callback for PHP methods and functions */
static void v8js_call_php_func(zval *value, zend_class_entry *ce, zend_function *method_ptr, v8::Isolate *isolate, const v8::FunctionCallbackInfo<v8::Value>& info TSRMLS_DC) /* {{{ */
{
v8::Handle<v8::Value> return_value;
v8::Handle<v8::Value> 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);