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 ;
@@ -512,6 +513,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
512513 * to pretend the exception happened during the YIELD opcode. */
513514 EG (current_execute_data ) = generator -> execute_data ;
514515 generator -> execute_data -> opline -- ;
516+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
517+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
515518 generator -> execute_data -> prev_execute_data = original_execute_data ;
516519
517520 if (exception ) {
@@ -520,13 +523,14 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
520523 zend_rethrow_exception (EG (current_execute_data ));
521524 }
522525
526+ generator -> execute_data -> opline ++ ;
527+
523528 /* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
524529 if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
525530 zval_ptr_dtor (& generator -> values );
526531 ZVAL_UNDEF (& generator -> values );
527532 }
528533
529- generator -> execute_data -> opline ++ ;
530534 EG (current_execute_data ) = original_execute_data ;
531535}
532536
@@ -656,8 +660,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
656660
657661static zend_result zend_generator_get_next_delegated_value (zend_generator * generator ) /* {{{ */
658662{
659- -- generator -> execute_data -> opline ;
660-
661663 zval * value ;
662664 if (Z_TYPE (generator -> values ) == IS_ARRAY ) {
663665 HashTable * ht = Z_ARR (generator -> values );
@@ -739,14 +741,12 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
739741 }
740742 }
741743
742- ++ generator -> execute_data -> opline ;
743744 return SUCCESS ;
744745
745746failure :
746747 zval_ptr_dtor (& generator -> values );
747748 ZVAL_UNDEF (& generator -> values );
748749
749- ++ generator -> execute_data -> opline ;
750750 return FAILURE ;
751751}
752752/* }}} */
@@ -811,6 +811,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
811811 generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
812812 return ;
813813 }
814+ if (UNEXPECTED (EG (exception ))) {
815+ /* Decrementing opline_before_exception to pretend the exception
816+ * happened during the YIELD_FROM opcode. */
817+ if (generator -> execute_data ) {
818+ ZEND_ASSERT (generator -> execute_data -> opline == EG (exception_op ));
819+ ZEND_ASSERT ((EG (opline_before_exception )- 1 )-> opcode == ZEND_YIELD_FROM );
820+ EG (opline_before_exception )-- ;
821+ }
822+ }
814823 /* If there are no more delegated values, resume the generator
815824 * after the "yield from" expression. */
816825 }
0 commit comments