Skip to content

Commit ceda8a8

Browse files
committed
Merge branch 'PHP-8.1'
2 parents db34e2a + e002556 commit ceda8a8

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Exceptions are properly appended when thrown from yield from values destruction
3+
--FILE--
4+
<?php
5+
6+
function gen() {
7+
yield from [1, 2, new class {
8+
function __destruct() {
9+
throw new Exception("dtor");
10+
}
11+
}];
12+
}
13+
14+
gen()->throw(new Exception("outer"));
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught Exception: outer in %s:%d
19+
Stack trace:
20+
#0 {main}
21+
22+
Next Exception: dtor in %s:%d
23+
Stack trace:
24+
#0 %s(%d): class@anonymous->__destruct()
25+
#1 [internal function]: gen()
26+
#2 %s(%d): Generator->throw(Object(Exception))
27+
#3 {main}
28+
thrown %s on line %d

Zend/zend_generators.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -458,21 +458,23 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
458458
{
459459
zend_execute_data *original_execute_data = EG(current_execute_data);
460460

461-
/* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
462-
if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) {
463-
zval_ptr_dtor(&generator->values);
464-
ZVAL_UNDEF(&generator->values);
465-
}
466-
467461
/* Throw the exception in the context of the generator. Decrementing the opline
468462
* to pretend the exception happened during the YIELD opcode. */
469463
EG(current_execute_data) = generator->execute_data;
470464
generator->execute_data->opline--;
465+
471466
if (exception) {
472467
zend_throw_exception_object(exception);
473468
} else {
474469
zend_rethrow_exception(EG(current_execute_data));
475470
}
471+
472+
/* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
473+
if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) {
474+
zval_ptr_dtor(&generator->values);
475+
ZVAL_UNDEF(&generator->values);
476+
}
477+
476478
generator->execute_data->opline++;
477479
EG(current_execute_data) = original_execute_data;
478480
}
@@ -603,6 +605,8 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
603605

604606
static zend_result zend_generator_get_next_delegated_value(zend_generator *generator) /* {{{ */
605607
{
608+
--generator->execute_data->opline;
609+
606610
zval *value;
607611
if (Z_TYPE(generator->values) == IS_ARRAY) {
608612
HashTable *ht = Z_ARR(generator->values);
@@ -683,11 +687,15 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
683687
ZVAL_LONG(&generator->key, iter->index);
684688
}
685689
}
690+
691+
++generator->execute_data->opline;
686692
return SUCCESS;
687693

688694
failure:
689695
zval_ptr_dtor(&generator->values);
690696
ZVAL_UNDEF(&generator->values);
697+
698+
++generator->execute_data->opline;
691699
return FAILURE;
692700
}
693701
/* }}} */

0 commit comments

Comments
 (0)