From: Nikita Popov Date: Fri, 3 Apr 2020 08:06:41 +0000 (+0200) Subject: Fixed bug #78434 X-Git-Tag: php-7.4.7RC1~73 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=823a956855c1f38ed8ee888bf248917e28d40314;p=php 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. --- diff --git a/NEWS b/NEWS index 67d71eca64..dd770268ae 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ PHP NEWS ?? ??? ????, PHP 7.4.6 +- Core: + . Fixed bug #78434 (Generator yields no items after valid() call). (Nikita) + - DOM: . Fixed bug #78221 (DOMNode::normalize() doesn't remove empty text nodes). (cmb) diff --git a/Zend/tests/generators/bug78434.phpt b/Zend/tests/generators/bug78434.phpt new file mode 100644 index 0000000000..dd9351e168 --- /dev/null +++ b/Zend/tests/generators/bug78434.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #78434: Generator skips first item after valid() call +--FILE-- +valid(); + yield from $generator; + + $generator = $function(); + $generator->valid(); + yield from $generator; +}; + +foreach ($wrapper() as $value) { + echo $value, "\n"; +} + +?> +--EXPECT-- +0 +0 diff --git a/Zend/tests/generators/yield_from_multi_tree.phpt b/Zend/tests/generators/yield_from_multi_tree.phpt index 9bec138149..808d693eae 100644 --- a/Zend/tests/generators/yield_from_multi_tree.phpt +++ b/Zend/tests/generators/yield_from_multi_tree.phpt @@ -10,9 +10,6 @@ function from($levels) { } function gen($gen, $level) { - if ($level % 2) { - yield $gen->current(); - } yield from $gen; } diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 7031e9a810..9d8546f518 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -609,6 +609,7 @@ void zend_generator_yield_from(zend_generator *generator, zend_generator *from) generator->node.parent = from; zend_generator_get_current(generator); GC_DELREF(&from->std); + generator->flags |= ZEND_GENERATOR_DO_INIT; } ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator, zend_generator *leaf) @@ -785,6 +786,7 @@ try_again: if (UNEXPECTED((orig_generator->flags & ZEND_GENERATOR_DO_INIT) != 0 && !Z_ISUNDEF(generator->value))) { /* We must not advance Generator if we yield from a Generator being currently run */ + orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT; return; } @@ -864,15 +866,15 @@ try_again: goto try_again; } } + + orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT; } /* }}} */ static inline void zend_generator_ensure_initialized(zend_generator *generator) /* {{{ */ { if (UNEXPECTED(Z_TYPE(generator->value) == IS_UNDEF) && EXPECTED(generator->execute_data) && EXPECTED(generator->node.parent == NULL)) { - generator->flags |= ZEND_GENERATOR_DO_INIT; zend_generator_resume(generator); - generator->flags &= ~ZEND_GENERATOR_DO_INIT; generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD; } }