瀏覽代碼

Improve PHP->JS->PHP exception back propagation

Stefan Siegl 9 年之前
父節點
當前提交
f7c33539c2
共有 5 個文件被更改,包括 63 次插入12 次删除
  1. 36 0
      tests/php_exceptions_004.phpt
  2. 3 2
      v8js_class.cc
  3. 16 4
      v8js_exceptions.cc
  4. 4 3
      v8js_exceptions.h
  5. 4 3
      v8js_v8.cc

+ 36 - 0
tests/php_exceptions_004.phpt

@@ -0,0 +1,36 @@
+--TEST--
+Test V8::executeString() : PHP Exception handling (PHP->JS->PHP back 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
+PHP.foo.throwException();
+// the exception should abort further execution,
+// hence the print must not pop up
+print("after throwException\\n");
+EOT;
+
+try {
+    $v8->executeString($JS, 'php_exceptions_004', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS);
+}
+catch(V8JsScriptException $e) {
+    echo "Got V8JsScriptException\n";
+    var_dump($e->getPrevious()->getMessage());
+}
+?>
+===EOF===
+--EXPECTF--
+Got V8JsScriptException
+string(14) "Test-Exception"
+===EOF===

+ 3 - 2
v8js_class.cc

@@ -2,12 +2,13 @@
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
-  | Copyright (c) 1997-2013 The PHP Group                                |
+  | Copyright (c) 1997-2015 The PHP Group                                |
   +----------------------------------------------------------------------+
   | http://www.opensource.org/licenses/mit-license.php  MIT License      |
   +----------------------------------------------------------------------+
   | Author: Jani Taskinen <[email protected]>                         |
   | Author: Patrick Reilly <[email protected]>                             |
+  | Author: Stefan Siegl <[email protected]>                                |
   +----------------------------------------------------------------------+
 */
 
@@ -498,7 +499,7 @@ static void v8js_compile_script(zval *this_ptr, const char *str, int str_len, co
 
 	/* Compile errors? */
 	if (script.IsEmpty()) {
-		v8js_throw_script_exception(&try_catch TSRMLS_CC);
+		v8js_throw_script_exception(c->isolate, &try_catch TSRMLS_CC);
 		return;
 	}
 	res = (v8js_script *)emalloc(sizeof(v8js_script));

+ 16 - 4
v8js_exceptions.cc

@@ -2,12 +2,13 @@
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
-  | Copyright (c) 1997-2013 The PHP Group                                |
+  | Copyright (c) 1997-2015 The PHP Group                                |
   +----------------------------------------------------------------------+
   | http://www.opensource.org/licenses/mit-license.php  MIT License      |
   +----------------------------------------------------------------------+
   | Author: Jani Taskinen <[email protected]>                         |
   | Author: Patrick Reilly <[email protected]>                             |
+  | Author: Stefan Siegl <[email protected]>                                |
   +----------------------------------------------------------------------+
 */
 
@@ -38,7 +39,7 @@ zend_class_entry *php_ce_v8js_memory_limit_exception;
 
 /* {{{ Class: V8JsScriptException */
 
-void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
+void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
 {
 	v8::String::Utf8Value exception(try_catch->Exception());
 	const char *exception_string = ToCString(exception);
@@ -81,6 +82,17 @@ void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TS
 			const char* stacktrace_string = ToCString(stacktrace);
 			PHPV8_EXPROP(_string, JsTrace, stacktrace_string);
 		}
+
+		if(try_catch->Exception()->IsObject()) {
+			v8::Local<v8::Value> php_ref = try_catch->Exception()->ToObject()->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY));
+
+			if(!php_ref.IsEmpty()) {
+				assert(php_ref->IsExternal());
+				zval *php_exception = reinterpret_cast<zval *>(v8::External::Cast(*php_ref)->Value());
+				zend_exception_set_previous(return_value, php_exception TSRMLS_CC);
+			}
+		}
+
 	}
 
 	PHPV8_EXPROP(_string, message, message_string);
@@ -89,7 +101,7 @@ void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TS
 }
 /* }}} */
 
-void v8js_throw_script_exception(v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
+void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
 {
 	v8::String::Utf8Value exception(try_catch->Exception());
 	const char *exception_string = ToCString(exception);
@@ -99,7 +111,7 @@ void v8js_throw_script_exception(v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
 		zend_throw_exception(php_ce_v8js_script_exception, (char *) exception_string, 0 TSRMLS_CC);
 	} else {
 		MAKE_STD_ZVAL(zexception);
-		v8js_create_script_exception(zexception, try_catch TSRMLS_CC);
+		v8js_create_script_exception(zexception, isolate, try_catch TSRMLS_CC);
 		zend_throw_exception_object(zexception TSRMLS_CC);
 	}
 }

+ 4 - 3
v8js_exceptions.h

@@ -2,12 +2,13 @@
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
-  | Copyright (c) 1997-2013 The PHP Group                                |
+  | Copyright (c) 1997-2015 The PHP Group                                |
   +----------------------------------------------------------------------+
   | http://www.opensource.org/licenses/mit-license.php  MIT License      |
   +----------------------------------------------------------------------+
   | Author: Jani Taskinen <[email protected]>                         |
   | Author: Patrick Reilly <[email protected]>                             |
+  | Author: Stefan Siegl <[email protected]>                                |
   +----------------------------------------------------------------------+
 */
 
@@ -19,8 +20,8 @@ extern zend_class_entry *php_ce_v8js_script_exception;
 extern zend_class_entry *php_ce_v8js_time_limit_exception;
 extern zend_class_entry *php_ce_v8js_memory_limit_exception;
 
-void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TSRMLS_DC);
-void v8js_throw_script_exception(v8::TryCatch *try_catch TSRMLS_DC);
+void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC);
+void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC);
 
 PHP_MINIT_FUNCTION(v8js_exceptions);
 

+ 4 - 3
v8js_v8.cc

@@ -2,12 +2,13 @@
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
-  | Copyright (c) 1997-2013 The PHP Group                                |
+  | Copyright (c) 1997-2015 The PHP Group                                |
   +----------------------------------------------------------------------+
   | http://www.opensource.org/licenses/mit-license.php  MIT License      |
   +----------------------------------------------------------------------+
   | Author: Jani Taskinen <[email protected]>                         |
   | Author: Patrick Reilly <[email protected]>                             |
+  | Author: Stefan Siegl <[email protected]>                                |
   +----------------------------------------------------------------------+
 */
 
@@ -175,14 +176,14 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value,
 
 			/* Report immediately if report_uncaught is true */
 			if (c->report_uncaught) {
-				v8js_throw_script_exception(&try_catch TSRMLS_CC);
+				v8js_throw_script_exception(c->isolate, &try_catch TSRMLS_CC);
 				return;
 			}
 
 			/* Exception thrown from JS, preserve it for future execution */
 			if (result.IsEmpty()) {
 				MAKE_STD_ZVAL(c->pending_exception);
-				v8js_create_script_exception(c->pending_exception, &try_catch TSRMLS_CC);
+				v8js_create_script_exception(c->pending_exception, c->isolate, &try_catch TSRMLS_CC);
 				return;
 			}
 		}