26
26
#include "zend_closures.h"
27
27
#include "zend_generators_arginfo.h"
28
28
#include "zend_observer.h"
29
+ #include "zend_vm_opcodes.h"
29
30
30
31
ZEND_API zend_class_entry * zend_ce_generator ;
31
32
ZEND_API zend_class_entry * zend_ce_ClosedGeneratorException ;
@@ -516,6 +517,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
516
517
* to pretend the exception happened during the YIELD opcode. */
517
518
EG (current_execute_data ) = generator -> execute_data ;
518
519
generator -> execute_data -> opline -- ;
520
+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
521
+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
519
522
generator -> execute_data -> prev_execute_data = original_execute_data ;
520
523
521
524
if (exception ) {
@@ -524,13 +527,14 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
524
527
zend_rethrow_exception (EG (current_execute_data ));
525
528
}
526
529
530
+ generator -> execute_data -> opline ++ ;
531
+
527
532
/* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
528
533
if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
529
534
zval_ptr_dtor (& generator -> values );
530
535
ZVAL_UNDEF (& generator -> values );
531
536
}
532
537
533
- generator -> execute_data -> opline ++ ;
534
538
EG (current_execute_data ) = original_execute_data ;
535
539
}
536
540
@@ -660,8 +664,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
660
664
661
665
static zend_result zend_generator_get_next_delegated_value (zend_generator * generator ) /* {{{ */
662
666
{
663
- -- generator -> execute_data -> opline ;
664
-
665
667
zval * value ;
666
668
if (Z_TYPE (generator -> values ) == IS_ARRAY ) {
667
669
HashTable * ht = Z_ARR (generator -> values );
@@ -743,14 +745,12 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
743
745
}
744
746
}
745
747
746
- ++ generator -> execute_data -> opline ;
747
748
return SUCCESS ;
748
749
749
750
failure :
750
751
zval_ptr_dtor (& generator -> values );
751
752
ZVAL_UNDEF (& generator -> values );
752
753
753
- ++ generator -> execute_data -> opline ;
754
754
return FAILURE ;
755
755
}
756
756
/* }}} */
@@ -815,6 +815,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
815
815
generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
816
816
return ;
817
817
}
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
+ }
818
827
/* If there are no more delegated values, resume the generator
819
828
* after the "yield from" expression. */
820
829
}
0 commit comments