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 ;
@@ -508,6 +509,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
508
509
* to pretend the exception happened during the YIELD opcode. */
509
510
EG (current_execute_data ) = generator -> execute_data ;
510
511
generator -> execute_data -> opline -- ;
512
+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
513
+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
511
514
generator -> execute_data -> prev_execute_data = original_execute_data ;
512
515
513
516
if (exception ) {
@@ -516,13 +519,14 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
516
519
zend_rethrow_exception (EG (current_execute_data ));
517
520
}
518
521
522
+ generator -> execute_data -> opline ++ ;
523
+
519
524
/* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
520
525
if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
521
526
zval_ptr_dtor (& generator -> values );
522
527
ZVAL_UNDEF (& generator -> values );
523
528
}
524
529
525
- generator -> execute_data -> opline ++ ;
526
530
EG (current_execute_data ) = original_execute_data ;
527
531
}
528
532
@@ -652,8 +656,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
652
656
653
657
static zend_result zend_generator_get_next_delegated_value (zend_generator * generator ) /* {{{ */
654
658
{
655
- -- generator -> execute_data -> opline ;
656
-
657
659
zval * value ;
658
660
if (Z_TYPE (generator -> values ) == IS_ARRAY ) {
659
661
HashTable * ht = Z_ARR (generator -> values );
@@ -735,14 +737,12 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
735
737
}
736
738
}
737
739
738
- ++ generator -> execute_data -> opline ;
739
740
return SUCCESS ;
740
741
741
742
failure :
742
743
zval_ptr_dtor (& generator -> values );
743
744
ZVAL_UNDEF (& generator -> values );
744
745
745
- ++ generator -> execute_data -> opline ;
746
746
return FAILURE ;
747
747
}
748
748
/* }}} */
@@ -807,6 +807,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
807
807
generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
808
808
return ;
809
809
}
810
+ if (UNEXPECTED (EG (exception ))) {
811
+ /* Decrementing opline_before_exception to pretend the exception
812
+ * happened during the YIELD_FROM opcode. */
813
+ if (generator -> execute_data ) {
814
+ ZEND_ASSERT (generator -> execute_data -> opline == EG (exception_op ));
815
+ ZEND_ASSERT ((EG (opline_before_exception )- 1 )-> opcode == ZEND_YIELD_FROM );
816
+ EG (opline_before_exception )-- ;
817
+ }
818
+ }
810
819
/* If there are no more delegated values, resume the generator
811
820
* after the "yield from" expression. */
812
821
}
0 commit comments