diff options
author | Nikita Popov <nikic@php.net> | 2013-09-29 20:19:40 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2013-09-29 20:19:40 +0200 |
commit | cbf0683c6f8adfd375f495d2ef5a3a50136a11a6 (patch) | |
tree | e516eb37799af9e4c74942252515ad9f2c8eb8a4 | |
parent | 9529b8f5c48dac70b99bfd2c1def0139c6e93f60 (diff) | |
parent | 6b68f44e6b46dffd7fe029eca7afc37f1fa57347 (diff) | |
download | php-git-cbf0683c6f8adfd375f495d2ef5a3a50136a11a6.tar.gz |
Merge branch 'PHP-5.5'
-rw-r--r-- | Zend/tests/bug64979.phpt | 18 | ||||
-rw-r--r-- | Zend/zend_generators.c | 28 |
2 files changed, 35 insertions, 11 deletions
diff --git a/Zend/tests/bug64979.phpt b/Zend/tests/bug64979.phpt index 09de555546..5bc8e5a6ab 100644 --- a/Zend/tests/bug64979.phpt +++ b/Zend/tests/bug64979.phpt @@ -1,15 +1,13 @@ --TEST--
-Bug #64578 (Closures with static variables can be generators)
---XFAIL--
-Bug #64979 not fixed yet.
+Bug #64979 (Wrong behavior of static variables in closure generators)
--FILE--
<?php
function new_closure_gen() {
- return function() {
- static $foo = 0;
- yield ++$foo;
- };
+ return function() {
+ static $foo = 0;
+ yield ++$foo;
+ };
}
$closure1 = new_closure_gen();
@@ -20,9 +18,9 @@ $gen2 = $closure1(); $gen3 = $closure2();
foreach (array($gen1, $gen2, $gen3) as $gen) {
- foreach ($gen as $val) {
- print "$val\n";
- }
+ foreach ($gen as $val) {
+ var_dump($val);
+ }
}
?>
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index c55dc67f1b..e8b1be4445 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -226,6 +226,16 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM } /* }}} */ +static void copy_closure_static_var(zval **var TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */ +{ + HashTable *target = va_arg(args, HashTable *); + + SEPARATE_ZVAL_TO_MAKE_IS_REF(var); + Z_ADDREF_PP(var); + zend_hash_quick_update(target, key->arKey, key->nKeyLength, key->h, var, sizeof(zval *), NULL); +} +/* }}} */ + /* Requires globals EG(scope), EG(current_scope), EG(This), * EG(active_symbol_table) and EG(current_execute_data). */ ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */ @@ -242,7 +252,23 @@ ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* if (op_array->fn_flags & ZEND_ACC_CLOSURE) { zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array)); *op_array_copy = *op_array; - function_add_ref((zend_function *) op_array_copy); + + (*op_array->refcount)++; + op_array->run_time_cache = NULL; + if (op_array->static_variables) { + ALLOC_HASHTABLE(op_array_copy->static_variables); + zend_hash_init( + op_array_copy->static_variables, + zend_hash_num_elements(op_array->static_variables), + NULL, ZVAL_PTR_DTOR, 0 + ); + zend_hash_apply_with_arguments( + op_array->static_variables TSRMLS_CC, + (apply_func_args_t) copy_closure_static_var, + 1, op_array_copy->static_variables + ); + } + op_array = op_array_copy; } |