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

Remove support for uncaught exceptions. Use try/catch.

This commit is contained in:
Stefan Siegl 2022-05-31 09:53:09 +02:00
parent fa4babb307
commit f6a93c3cd6
11 changed files with 9 additions and 364 deletions

View File

@ -78,10 +78,9 @@ class V8Js
* Initializes and starts V8 engine and returns new V8Js object with it's own V8 context. * Initializes and starts V8 engine and returns new V8Js object with it's own V8 context.
* @param string $object_name * @param string $object_name
* @param array $variables * @param array $variables
* @param bool $report_uncaught_exceptions
* @param string $snapshot_blob * @param string $snapshot_blob
*/ */
public function __construct($object_name = "PHP", array $variables = [], $report_uncaught_exceptions = TRUE, $snapshot_blob = NULL) public function __construct($object_name = "PHP", array $variables = [], $snapshot_blob = NULL)
{} {}
/** /**
@ -358,8 +357,7 @@ Exceptions
========== ==========
If the JavaScript code throws (without catching), causes errors or doesn't If the JavaScript code throws (without catching), causes errors or doesn't
compile, `V8JsScriptException` exceptions are thrown unless the `V8Js` object compile, `V8JsScriptException` exceptions are thrown.
is constructed with `report_uncaught_exceptions` set `FALSE`.
PHP exceptions that occur due to calls from JavaScript code by default are PHP exceptions that occur due to calls from JavaScript code by default are
*not* re-thrown into JavaScript context but cause the JavaScript execution to *not* re-thrown into JavaScript context but cause the JavaScript execution to

View File

@ -22,7 +22,7 @@ if (strlen($snap) > 0) {
var_dump("snapshot successfully created"); var_dump("snapshot successfully created");
} }
$v8 = new V8Js('PHP', array(), true, $snap); $v8 = new V8Js('PHP', array(), $snap);
$v8->executeString('var_dump(doublify(23));'); $v8->executeString('var_dump(doublify(23));');
?> ?>
===EOF=== ===EOF===

View File

@ -1,90 +0,0 @@
--TEST--
Test V8::executeString() : Exception clearing test
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
$v8 = new V8Js(null, array(), false);
var_dump($v8->getPendingException());
$v8->clearPendingException();
var_dump($v8->getPendingException());
$v8->executeString('fooobar', 'throw_0');
var_dump($v8->getPendingException());
$v8->clearPendingException();
var_dump($v8->getPendingException());
?>
===EOF===
--EXPECTF--
Deprecated: V8Js::__construct(): Disabling exception reporting is deprecated, $report_uncaught_exceptions != true in %s%eexception_clearing.php on line 3
Deprecated: %s V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 5
NULL
Deprecated: %s V8Js::clearPendingException() is deprecated in %s%eexception_clearing.php on line 7
Deprecated: %s V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 8
NULL
Deprecated: %s V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 11
object(V8JsScriptException)#%d (13) {
["message":protected]=>
string(49) "throw_0:1: ReferenceError: fooobar is not defined"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(%d) "%s"
["line":protected]=>
int(10)
["trace":"Exception":private]=>
array(1) {
[0]=>
array(6) {
["file"]=>
string(%d) "%s"
["line"]=>
int(10)
["function"]=>
string(13) "executeString"
["class"]=>
string(4) "V8Js"
["type"]=>
string(2) "->"
["args"]=>
array(2) {
[0]=>
string(7) "fooobar"
[1]=>
string(7) "throw_0"
}
}
}
["previous":"Exception":private]=>
NULL
["JsFileName":protected]=>
string(7) "throw_0"
["JsLineNumber":protected]=>
int(1)
["JsStartColumn":protected]=>
int(0)
["JsEndColumn":protected]=>
int(1)
["JsSourceLine":protected]=>
string(7) "fooobar"
["JsTrace":protected]=>
string(57) "ReferenceError: fooobar is not defined
at throw_0:1:1"
}
Deprecated: %s V8Js::clearPendingException() is deprecated in %s%eexception_clearing.php on line 13
Deprecated: %s V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 14
NULL
===EOF===

View File

@ -1,37 +0,0 @@
--TEST--
Test V8::executeString() : Exception propagation test 1
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
private $v8 = NULL;
public function __construct()
{
$this->v8 = new V8Js();
$this->v8->foo = $this;
$this->v8->executeString('fooobar', 'throw_0');
var_dump($this->v8->getPendingException());
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch1');
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch2');
}
public function bar()
{
echo "To Bar!\n";
$this->v8->executeString('throw new Error();', 'throw_1');
}
}
try {
$foo = new Foo();
} catch (V8JsScriptException $e) {
echo "PHP Exception: ", $e->getMessage(), "\n"; //var_dump($e);
}
?>
===EOF===
--EXPECTF--
PHP Exception: throw_0:1: ReferenceError: fooobar is not defined
===EOF===

View File

@ -1,112 +0,0 @@
--TEST--
Test V8::executeString() : Exception propagation test 2
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
private $v8 = NULL;
public function __construct()
{
$this->v8 = new V8Js(null, array(), false);
$this->v8->foo = $this;
$this->v8->executeString('fooobar', 'throw_0');
var_dump($this->v8->getPendingException());
// the exception is not cleared before the next executeString call,
// hence the next *exiting* executeString will throw.
// In this case this is the executeString call in bar() function.
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch1');
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch2');
}
public function bar()
{
echo "To Bar!\n";
// This executeString call throws a PHP exception, not propagated
// to JS, hence immediately triggering the top-level catch handler.
$this->v8->executeString('throw new Error();', 'throw_1');
}
}
try {
$foo = new Foo();
} catch (V8JsScriptException $e) {
echo "PHP Exception: ", $e->getMessage(), "\n"; //var_dump($e);
}
?>
===EOF===
--EXPECTF--
Deprecated: V8Js::__construct(): Disabling exception reporting is deprecated, $report_uncaught_exceptions != true in %s%eexception_propagation_2.php on line 8
Deprecated: %s V8Js::getPendingException() is deprecated in %s%eexception_propagation_2.php on line 11
object(V8JsScriptException)#%d (13) {
["message":protected]=>
string(49) "throw_0:1: ReferenceError: fooobar is not defined"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(%d) "%s"
["line":protected]=>
int(10)
["trace":"Exception":private]=>
array(2) {
[0]=>
array(6) {
["file"]=>
string(%d) "%s"
["line"]=>
int(10)
["function"]=>
string(13) "executeString"
["class"]=>
string(4) "V8Js"
["type"]=>
string(2) "->"
["args"]=>
array(2) {
[0]=>
string(7) "fooobar"
[1]=>
string(7) "throw_0"
}
}
[1]=>
array(6) {
["file"]=>
string(%d) "%s"
["line"]=>
int(29)
["function"]=>
string(11) "__construct"
["class"]=>
string(3) "Foo"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
}
["previous":"Exception":private]=>
NULL
["JsFileName":protected]=>
string(7) "throw_0"
["JsLineNumber":protected]=>
int(1)
["JsStartColumn":protected]=>
int(0)
["JsEndColumn":protected]=>
int(1)
["JsSourceLine":protected]=>
string(7) "fooobar"
["JsTrace":protected]=>
string(57) "ReferenceError: fooobar is not defined
at throw_0:1:1"
}
To Bar!
PHP Exception: throw_0:1: ReferenceError: fooobar is not defined
===EOF===

View File

@ -1,39 +0,0 @@
--TEST--
Test V8::executeString() : Exception propagation test 3
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
private $v8 = NULL;
public function __construct()
{
$this->v8 = new V8Js(null, array(), false);
$this->v8->foo = $this;
$this->v8->executeString('function foobar() { throw new SyntaxError(); }', 'throw_1');
$this->v8->executeString('try { foobar(); } catch (e) { print(e + " caught in JS!\n"); }', 'trycatch1');
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught via PHP callback!\n"); }', 'trycatch2');
}
public function bar()
{
echo "To Bar!\n";
$this->v8->executeString('throw new Error();', 'throw_2');
}
}
try {
$foo = new Foo();
} catch (V8JsScriptException $e) {
echo "PHP Exception: ", $e->getMessage(), "\n";
}
?>
===EOF===
--EXPECTF--
Deprecated: V8Js::__construct(): Disabling exception reporting is deprecated, $report_uncaught_exceptions != true in %s%eexception_propagation_3.php on line 8
SyntaxError caught in JS!
To Bar!
Error caught via PHP callback!
===EOF===

View File

@ -19,7 +19,6 @@ var_dump(typeof PHP.executeString);
var_dump(typeof PHP.compileString); var_dump(typeof PHP.compileString);
var_dump(typeof PHP.executeScript); var_dump(typeof PHP.executeScript);
var_dump(typeof PHP.checkString); var_dump(typeof PHP.checkString);
var_dump(typeof PHP.getPendingException);
var_dump(typeof PHP.setModuleNormaliser); var_dump(typeof PHP.setModuleNormaliser);
var_dump(typeof PHP.setModuleLoader); var_dump(typeof PHP.setModuleLoader);
var_dump(typeof PHP.registerExtension); var_dump(typeof PHP.registerExtension);
@ -52,6 +51,5 @@ string(9) "undefined"
string(9) "undefined" string(9) "undefined"
string(9) "undefined" string(9) "undefined"
string(9) "undefined" string(9) "undefined"
string(9) "undefined"
string(6) "caught" string(6) "caught"
===EOF=== ===EOF===

View File

@ -12,7 +12,7 @@ $unicode = 'äöüßÜÄÖÜ߀áàâÁÀµ²³▁▂▃▄▅▆▇█
$snapshot = V8Js::createSnapshot("var snapshot = {unicode: '" . $unicode . "'}"); $snapshot = V8Js::createSnapshot("var snapshot = {unicode: '" . $unicode . "'}");
# start V8Js # start V8Js
$jscript = new V8Js('php', array(), true, $snapshot); $jscript = new V8Js('php', array(), $snapshot);
# insert unicode via php var # insert unicode via php var
$jscript->unicode = $unicode; $jscript->unicode = $unicode;

View File

@ -78,7 +78,6 @@ static void v8js_free_storage(zend_object *object) /* {{{ */
zend_object_std_dtor(&c->std); zend_object_std_dtor(&c->std);
zval_ptr_dtor(&c->pending_exception);
zval_ptr_dtor(&c->module_normaliser); zval_ptr_dtor(&c->module_normaliser);
zval_ptr_dtor(&c->module_loader); zval_ptr_dtor(&c->module_loader);
@ -250,12 +249,11 @@ static void v8js_fatal_error_handler(const char *location, const char *message)
((ZSTR_LEN(key) == sizeof(mname) - 1) && \ ((ZSTR_LEN(key) == sizeof(mname) - 1) && \
!strncasecmp(ZSTR_VAL(key), mname, ZSTR_LEN(key))) !strncasecmp(ZSTR_VAL(key), mname, ZSTR_LEN(key)))
/* {{{ proto void V8Js::__construct([string object_name [, array variables [, bool report_uncaught_exceptions [, string snapshot_blob]]]]) /* {{{ proto void V8Js::__construct([string object_name [, array variables [, string snapshot_blob]]])
__construct for V8Js */ __construct for V8Js */
static PHP_METHOD(V8Js, __construct) static PHP_METHOD(V8Js, __construct)
{ {
zend_string *object_name = NULL; zend_string *object_name = NULL;
zend_bool report_uncaught = 1;
zval *vars_arr = NULL; zval *vars_arr = NULL;
zval *snapshot_blob = NULL; zval *snapshot_blob = NULL;
@ -266,7 +264,7 @@ static PHP_METHOD(V8Js, __construct)
return; return;
} }
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!abz", &object_name, &vars_arr, &report_uncaught, &snapshot_blob) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!az", &object_name, &vars_arr, &snapshot_blob) == FAILURE) {
return; return;
} }
@ -274,14 +272,8 @@ static PHP_METHOD(V8Js, __construct)
v8js_v8_init(); v8js_v8_init();
/* Throw PHP exception if uncaught exceptions exist */ /* Throw PHP exception if uncaught exceptions exist */
c->report_uncaught = report_uncaught;
ZVAL_NULL(&c->pending_exception);
c->in_execution = 0; c->in_execution = 0;
if (report_uncaught != 1) {
php_error_docref(NULL, E_DEPRECATED, "Disabling exception reporting is deprecated, $report_uncaught_exceptions != true");
}
new (&c->create_params) v8::Isolate::CreateParams(); new (&c->create_params) v8::Isolate::CreateParams();
#ifdef USE_INTERNAL_ALLOCATOR #ifdef USE_INTERNAL_ALLOCATOR
@ -703,43 +695,6 @@ static PHP_METHOD(V8Js, checkString)
} }
/* }}} */ /* }}} */
/* {{{ proto mixed V8Js::getPendingException()
*/
static PHP_METHOD(V8Js, getPendingException)
{
v8js_ctx *c;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
c = Z_V8JS_CTX_OBJ_P(getThis());
if (Z_TYPE(c->pending_exception) == IS_OBJECT) {
RETURN_ZVAL(&c->pending_exception, 1, 0);
}
}
/* }}} */
/* {{{ proto void V8Js::clearPendingException()
*/
static PHP_METHOD(V8Js, clearPendingException)
{
v8js_ctx *c;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
c = Z_V8JS_CTX_OBJ_P(getThis());
if (Z_TYPE(c->pending_exception) == IS_OBJECT) {
zval_ptr_dtor(&c->pending_exception);
ZVAL_NULL(&c->pending_exception);
}
}
/* }}} */
/* {{{ proto void V8Js::setModuleNormaliser(string base, string module_id) /* {{{ proto void V8Js::setModuleNormaliser(string base, string module_id)
*/ */
static PHP_METHOD(V8Js, setModuleNormaliser) static PHP_METHOD(V8Js, setModuleNormaliser)
@ -966,7 +921,6 @@ static PHP_METHOD(V8Js, createSnapshot)
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_construct, 0, 0, 0) ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_construct, 0, 0, 0)
ZEND_ARG_INFO(0, object_name) ZEND_ARG_INFO(0, object_name)
ZEND_ARG_INFO(0, variables) ZEND_ARG_INFO(0, variables)
ZEND_ARG_INFO(0, report_uncaught_exceptions)
ZEND_ARG_INFO(0, snapshot_blob) ZEND_ARG_INFO(0, snapshot_blob)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
@ -1000,12 +954,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_checkstring, 0, 0, 1)
ZEND_ARG_INFO(0, script) ZEND_ARG_INFO(0, script)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_v8js_getpendingexception, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_v8js_clearpendingexception, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmodulenormaliser, 0, 0, 2) ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmodulenormaliser, 0, 0, 2)
ZEND_ARG_INFO(0, base) ZEND_ARG_INFO(0, base)
ZEND_ARG_INFO(0, module_id) ZEND_ARG_INFO(0, module_id)
@ -1040,8 +988,6 @@ const zend_function_entry v8js_methods[] = { /* {{{ */
PHP_ME(V8Js, compileString, arginfo_v8js_compilestring, ZEND_ACC_PUBLIC) PHP_ME(V8Js, compileString, arginfo_v8js_compilestring, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, executeScript, arginfo_v8js_executescript, ZEND_ACC_PUBLIC) PHP_ME(V8Js, executeScript, arginfo_v8js_executescript, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, checkString, arginfo_v8js_checkstring, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) PHP_ME(V8Js, checkString, arginfo_v8js_checkstring, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(V8Js, getPendingException, arginfo_v8js_getpendingexception, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(V8Js, clearPendingException, arginfo_v8js_clearpendingexception, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(V8Js, setModuleNormaliser, arginfo_v8js_setmodulenormaliser, ZEND_ACC_PUBLIC) PHP_ME(V8Js, setModuleNormaliser, arginfo_v8js_setmodulenormaliser, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC) PHP_ME(V8Js, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, setTimeLimit, arginfo_v8js_settimelimit, ZEND_ACC_PUBLIC) PHP_ME(V8Js, setTimeLimit, arginfo_v8js_settimelimit, ZEND_ACC_PUBLIC)

View File

@ -37,8 +37,6 @@ struct cmp_str {
struct v8js_ctx { struct v8js_ctx {
v8::Persistent<v8::String> object_name; v8::Persistent<v8::String> object_name;
v8::Persistent<v8::Context> context; v8::Persistent<v8::Context> context;
zend_bool report_uncaught;
zval pending_exception;
int in_execution; int in_execution;
v8::Isolate *isolate; v8::Isolate *isolate;

View File

@ -224,33 +224,16 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value,
return; return;
} }
/* There was pending exception left from earlier executions -> throw to PHP */
if (Z_TYPE(c->pending_exception) == IS_OBJECT) {
zend_throw_exception_object(&c->pending_exception);
ZVAL_NULL(&c->pending_exception);
}
/* Handle runtime JS exceptions */ /* Handle runtime JS exceptions */
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
/* Pending exceptions are set only in outer caller, inner caller exceptions are always rethrown */ /* Pending exceptions are set only in outer caller, inner caller exceptions are always rethrown */
if (c->in_execution < 1) { if (c->in_execution < 1) {
/* Report immediately if report_uncaught is true */
if (c->report_uncaught) {
v8js_throw_script_exception(c->isolate, &try_catch); v8js_throw_script_exception(c->isolate, &try_catch);
zval_ptr_dtor(&zv_v8inst); zval_ptr_dtor(&zv_v8inst);
return; return;
} }
/* Exception thrown from JS, preserve it for future execution */
if (result.IsEmpty()) {
v8js_create_script_exception(&c->pending_exception, c->isolate, &try_catch);
zval_ptr_dtor(&zv_v8inst);
return;
}
}
/* Rethrow back to JS */ /* Rethrow back to JS */
try_catch.ReThrow(); try_catch.ReThrow();
zval_ptr_dtor(&zv_v8inst); zval_ptr_dtor(&zv_v8inst);