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 ;
@@ -512,6 +513,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
512
513
* to pretend the exception happened during the YIELD opcode. */
513
514
EG (current_execute_data ) = generator -> execute_data ;
514
515
generator -> execute_data -> opline -- ;
516
+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
517
+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
515
518
generator -> execute_data -> prev_execute_data = original_execute_data ;
516
519
517
520
if (exception ) {
@@ -520,13 +523,14 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
520
523
zend_rethrow_exception (EG (current_execute_data ));
521
524
}
522
525
526
+ generator -> execute_data -> opline ++ ;
527
+
523
528
/* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
524
529
if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
525
530
zval_ptr_dtor (& generator -> values );
526
531
ZVAL_UNDEF (& generator -> values );
527
532
}
528
533
529
- generator -> execute_data -> opline ++ ;
530
534
EG (current_execute_data ) = original_execute_data ;
531
535
}
532
536
@@ -656,8 +660,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
656
660
657
661
static zend_result zend_generator_get_next_delegated_value (zend_generator * generator ) /* {{{ */
658
662
{
659
- -- generator -> execute_data -> opline ;
660
-
661
663
zval * value ;
662
664
if (Z_TYPE (generator -> values ) == IS_ARRAY ) {
663
665
HashTable * ht = Z_ARR (generator -> values );
@@ -739,14 +741,12 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
739
741
}
740
742
}
741
743
742
- ++ generator -> execute_data -> opline ;
743
744
return SUCCESS ;
744
745
745
746
failure :
746
747
zval_ptr_dtor (& generator -> values );
747
748
ZVAL_UNDEF (& generator -> values );
748
749
749
- ++ generator -> execute_data -> opline ;
750
750
return FAILURE ;
751
751
}
752
752
/* }}} */
@@ -811,6 +811,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
811
811
generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
812
812
return ;
813
813
}
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
+ }
814
823
/* If there are no more delegated values, resume the generator
815
824
* after the "yield from" expression. */
816
825
}
0 commit comments