mirror of
https://github.com/php/php-src.git
synced 2025-01-25 05:04:20 +08:00
- MFH Rebind closure when binding to property
This commit is contained in:
parent
7ca830742e
commit
0e131653c1
28
Zend/tests/closure_033.phpt
Executable file
28
Zend/tests/closure_033.phpt
Executable file
@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
Closure 033: Dynamic closure property and private function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Test {
|
||||
public $func;
|
||||
function __construct() {
|
||||
$this->func = function() {
|
||||
echo __METHOD__ . "()\n";
|
||||
};
|
||||
}
|
||||
private function func() {
|
||||
echo __METHOD__ . "()\n";
|
||||
}
|
||||
}
|
||||
|
||||
$o = new Test;
|
||||
$f = $o->func;
|
||||
$f();
|
||||
$o->func();
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
Test::{closure}()
|
||||
|
||||
Fatal error: Call to private method Test::func() from context '' in %sclosure_033.php on line %d
|
233
Zend/tests/closure_034.phpt
Executable file
233
Zend/tests/closure_034.phpt
Executable file
@ -0,0 +1,233 @@
|
||||
--TEST--
|
||||
Closure 034: var_dump() of a Closure
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$outer = 25;
|
||||
|
||||
class Test {
|
||||
public $func1;
|
||||
public $var = 42;
|
||||
function __construct() {
|
||||
global $outer;
|
||||
$this->func1 = function($param, $other = "default") use ($outer) {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$o = new Test;
|
||||
var_dump($o->func1);
|
||||
|
||||
$o->func2 = function($param, $other = "default") use ($outer) {
|
||||
};
|
||||
|
||||
var_dump($o->func2);
|
||||
|
||||
$func3 = function($param, $other = "default") use ($outer) {
|
||||
};
|
||||
|
||||
var_dump($func3);
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
object(Test)#%d (2) {
|
||||
["func1"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
object(Test)#%d (2) {
|
||||
["func1"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
*RECURSION*
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
["var"]=>
|
||||
int(42)
|
||||
}
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
["var"]=>
|
||||
int(42)
|
||||
}
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
object(Test)#%d (3) {
|
||||
["func1"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
object(Test)#%d (3) {
|
||||
["func1"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
*RECURSION*
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
["var"]=>
|
||||
int(42)
|
||||
["func2"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
*RECURSION*
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
&int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
}
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
["var"]=>
|
||||
int(42)
|
||||
["func2"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
object(Test)#%d (3) {
|
||||
["func1"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
*RECURSION*
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
["var"]=>
|
||||
int(42)
|
||||
["func2"]=>
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
*RECURSION*
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
&int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
}
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
&int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
}
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
&int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
object(Closure)#%d (3) {
|
||||
["this"]=>
|
||||
NULL
|
||||
["static"]=>
|
||||
array(1) {
|
||||
["outer"]=>
|
||||
int(25)
|
||||
}
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$param"]=>
|
||||
string(10) "<required>"
|
||||
["$other"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
===DONE===
|
@ -118,6 +118,17 @@ ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval* zend_closure_copy(zval *closure_obj, zval *this_ptr TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure;
|
||||
|
||||
zval_copy_ctor(closure_obj);
|
||||
closure = (zend_closure *)zend_object_store_get_object(closure_obj TSRMLS_CC);
|
||||
closure->this_ptr = this_ptr;
|
||||
return closure_obj;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *lc_name;
|
||||
@ -238,7 +249,7 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
|
||||
static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *rv;
|
||||
|
@ -35,6 +35,7 @@ ZEND_API int zend_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_functio
|
||||
ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC);
|
||||
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC);
|
||||
ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC);
|
||||
ZEND_API zval* zend_closure_copy(zval *closure, zval *this_ptr TSRMLS_DC);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
@ -405,6 +405,10 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
|
||||
member = tmp_member;
|
||||
}
|
||||
|
||||
if (value && Z_TYPE_P(value) == IS_OBJECT && Z_OBJCE_P(value) == zend_ce_closure && zend_get_closure_this_ptr(value TSRMLS_CC) != object) {
|
||||
value = zend_closure_copy(value, object TSRMLS_CC);
|
||||
}
|
||||
|
||||
property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__set != NULL) TSRMLS_CC);
|
||||
|
||||
if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
|
||||
|
Loading…
Reference in New Issue
Block a user