Skip to content

Commit 823a956

Browse files
committed
Fixed bug #78434
The DO_INIT flag, which will skip the first resume on a primed generator, should always be set when starting to yield from a new generator, not only when the yield from happens during priming.
1 parent 1327491 commit 823a956

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ PHP NEWS
33

44
?? ??? ????, PHP 7.4.6
55

6+
- Core:
7+
. Fixed bug #78434 (Generator yields no items after valid() call). (Nikita)
8+
69
- DOM:
710
. Fixed bug #78221 (DOMNode::normalize() doesn't remove empty text nodes).
811
(cmb)

Zend/tests/generators/bug78434.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #78434: Generator skips first item after valid() call
3+
--FILE--
4+
<?php
5+
6+
$function = function () {
7+
yield 0;
8+
};
9+
10+
$wrapper = function () use ($function) {
11+
$generator = $function();
12+
$generator->valid();
13+
yield from $generator;
14+
15+
$generator = $function();
16+
$generator->valid();
17+
yield from $generator;
18+
};
19+
20+
foreach ($wrapper() as $value) {
21+
echo $value, "\n";
22+
}
23+
24+
?>
25+
--EXPECT--
26+
0
27+
0

Zend/tests/generators/yield_from_multi_tree.phpt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ function from($levels) {
1010
}
1111

1212
function gen($gen, $level) {
13-
if ($level % 2) {
14-
yield $gen->current();
15-
}
1613
yield from $gen;
1714
}
1815

Zend/zend_generators.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ void zend_generator_yield_from(zend_generator *generator, zend_generator *from)
609609
generator->node.parent = from;
610610
zend_generator_get_current(generator);
611611
GC_DELREF(&from->std);
612+
generator->flags |= ZEND_GENERATOR_DO_INIT;
612613
}
613614

614615
ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator, zend_generator *leaf)
@@ -785,6 +786,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
785786

786787
if (UNEXPECTED((orig_generator->flags & ZEND_GENERATOR_DO_INIT) != 0 && !Z_ISUNDEF(generator->value))) {
787788
/* We must not advance Generator if we yield from a Generator being currently run */
789+
orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT;
788790
return;
789791
}
790792

@@ -864,15 +866,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
864866
goto try_again;
865867
}
866868
}
869+
870+
orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT;
867871
}
868872
/* }}} */
869873

870874
static inline void zend_generator_ensure_initialized(zend_generator *generator) /* {{{ */
871875
{
872876
if (UNEXPECTED(Z_TYPE(generator->value) == IS_UNDEF) && EXPECTED(generator->execute_data) && EXPECTED(generator->node.parent == NULL)) {
873-
generator->flags |= ZEND_GENERATOR_DO_INIT;
874877
zend_generator_resume(generator);
875-
generator->flags &= ~ZEND_GENERATOR_DO_INIT;
876878
generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD;
877879
}
878880
}

0 commit comments

Comments
 (0)