2626#include "zend_closures.h"
2727#include "zend_generators_arginfo.h"
2828#include "zend_observer.h"
29+ #include "zend_vm_opcodes.h"
2930
3031ZEND_API zend_class_entry * zend_ce_generator ;
3132ZEND_API zend_class_entry * zend_ce_ClosedGeneratorException ;
@@ -516,6 +517,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
516517 * to pretend the exception happened during the YIELD opcode. */
517518 EG (current_execute_data ) = generator -> execute_data ;
518519 generator -> execute_data -> opline -- ;
520+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
521+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
519522 generator -> execute_data -> prev_execute_data = original_execute_data ;
520523
521524 if (exception ) {
@@ -524,13 +527,14 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
524527 zend_rethrow_exception (EG (current_execute_data ));
525528 }
526529
530+ generator -> execute_data -> opline ++ ;
531+
527532 /* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
528533 if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
529534 zval_ptr_dtor (& generator -> values );
530535 ZVAL_UNDEF (& generator -> values );
531536 }
532537
533- generator -> execute_data -> opline ++ ;
534538 EG (current_execute_data ) = original_execute_data ;
535539}
536540
@@ -660,8 +664,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
660664
661665static zend_result zend_generator_get_next_delegated_value (zend_generator * generator ) /* {{{ */
662666{
663- -- generator -> execute_data -> opline ;
664-
665667 zval * value ;
666668 if (Z_TYPE (generator -> values ) == IS_ARRAY ) {
667669 HashTable * ht = Z_ARR (generator -> values );
@@ -743,14 +745,12 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
743745 }
744746 }
745747
746- ++ generator -> execute_data -> opline ;
747748 return SUCCESS ;
748749
749750failure :
750751 zval_ptr_dtor (& generator -> values );
751752 ZVAL_UNDEF (& generator -> values );
752753
753- ++ generator -> execute_data -> opline ;
754754 return FAILURE ;
755755}
756756/* }}} */
@@ -815,6 +815,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
815815 generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
816816 return ;
817817 }
818+ if (UNEXPECTED (EG (exception ))) {
819+ /* Decrementing opline_before_exception to pretend the exception
820+ * happened during the YIELD_FROM opcode. */
821+ if (generator -> execute_data ) {
822+ ZEND_ASSERT (generator -> execute_data -> opline == EG (exception_op ));
823+ ZEND_ASSERT ((EG (opline_before_exception )- 1 )-> opcode == ZEND_YIELD_FROM );
824+ EG (opline_before_exception )-- ;
825+ }
826+ }
818827 /* If there are no more delegated values, resume the generator
819828 * after the "yield from" expression. */
820829 }
0 commit comments