@@ -64,6 +64,37 @@ static inline void php_v8_isolate_destroy(php_v8_isolate_t *php_v8_isolate) {
6464 }
6565}
6666
67+ void php_v8_isolate_external_exceptions_maybe_clear (php_v8_isolate_t *php_v8_isolate) {
68+ if (!php_v8_isolate->limits .depth ) {
69+ php_v8_isolate->external_exceptions ->clear ();
70+ }
71+ }
72+
73+ namespace phpv8 {
74+ int ExternalExceptionsStack::getGcCount () {
75+ return static_cast <int >(exceptions.size ());
76+ }
77+ void ExternalExceptionsStack::collectGcZvals (zval *& zv) {
78+ for (auto const &item : exceptions) {
79+ ZVAL_COPY_VALUE (zv++, &item);
80+ }
81+ }
82+ void ExternalExceptionsStack::add (zval zv) {
83+ assert (IS_OBJECT == Z_TYPE (zv));
84+ Z_ADDREF (zv);
85+ exceptions.push_back (zv);
86+ assert (exceptions.size () < INT_MAX);
87+ }
88+ void ExternalExceptionsStack::clear () {
89+ for (auto &item : exceptions) {
90+ zval_ptr_dtor (&item);
91+ }
92+ exceptions.clear ();
93+ }
94+ ExternalExceptionsStack::~ExternalExceptionsStack () {
95+ clear ();
96+ }
97+ }
6798
6899static HashTable * php_v8_isolate_gc (zval *object, zval **table, int *n) {
69100 PHP_V8_ISOLATE_FETCH_INTO (object, php_v8_isolate);
@@ -73,6 +104,7 @@ static HashTable * php_v8_isolate_gc(zval *object, zval **table, int *n) {
73104 size += php_v8_isolate->weak_function_templates ->getGcCount ();
74105 size += php_v8_isolate->weak_object_templates ->getGcCount ();
75106 size += php_v8_isolate->weak_values ->getGcCount ();
107+ size += php_v8_isolate->external_exceptions ->getGcCount ();
76108
77109 if (php_v8_isolate->gc_data_count < size) {
78110 php_v8_isolate->gc_data = (zval *)safe_erealloc (php_v8_isolate->gc_data , size, sizeof (zval), 0 );
@@ -85,6 +117,7 @@ static HashTable * php_v8_isolate_gc(zval *object, zval **table, int *n) {
85117 php_v8_isolate->weak_function_templates ->collectGcZvals (gc_data);
86118 php_v8_isolate->weak_object_templates ->collectGcZvals (gc_data);
87119 php_v8_isolate->weak_values ->collectGcZvals (gc_data);
120+ php_v8_isolate->external_exceptions ->collectGcZvals (gc_data);
88121
89122 *table = php_v8_isolate->gc_data ;
90123 *n = php_v8_isolate->gc_data_count ;
@@ -109,6 +142,10 @@ static void php_v8_isolate_free(zend_object *object) {
109142 delete php_v8_isolate->weak_values ;
110143 }
111144
145+ if (php_v8_isolate->external_exceptions ) {
146+ delete php_v8_isolate->external_exceptions ;
147+ }
148+
112149 if (php_v8_isolate->gc_data ) {
113150 efree (php_v8_isolate->gc_data );
114151 }
@@ -159,6 +196,7 @@ static zend_object *php_v8_isolate_ctor(zend_class_entry *ce) {
159196 php_v8_isolate->weak_function_templates = new phpv8::PersistentCollection<v8::FunctionTemplate>();
160197 php_v8_isolate->weak_object_templates = new phpv8::PersistentCollection<v8::ObjectTemplate>();
161198 php_v8_isolate->weak_values = new phpv8::PersistentCollection<v8::Value>();
199+ php_v8_isolate->external_exceptions = new phpv8::ExternalExceptionsStack ();
162200 new (&php_v8_isolate->key ) v8::Persistent<v8::Private>();
163201
164202 php_v8_isolate->std .handlers = &php_v8_isolate_object_handlers;
@@ -409,6 +447,7 @@ static PHP_METHOD(Isolate, getEnteredContext) {
409447}
410448
411449static PHP_METHOD (Isolate, throwException) {
450+ zval tmp;
412451 zval *php_v8_context_zv;
413452 zval *php_v8_value_zv;
414453 zval *exception_zv = NULL ;
@@ -444,6 +483,9 @@ static PHP_METHOD(Isolate, throwException) {
444483 }
445484
446485 ZVAL_COPY (&php_v8_value->exception , exception_zv);
486+
487+ ZVAL_OBJ (&tmp, &php_v8_value->std );
488+ php_v8_isolate->external_exceptions ->add (tmp);
447489 }
448490
449491 isolate->ThrowException (local_value);
0 commit comments