mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Let closure created from magic method accept named parameters
Implements GH-11348. Closes GH-11364.
This commit is contained in:
parent
16a63d7b07
commit
61e1f8aaeb
4 changed files with 128 additions and 2 deletions
2
NEWS
2
NEWS
|
@ -40,6 +40,8 @@ PHP NEWS
|
||||||
. Fix bug #79836 (Segfault in concat_function). (nielsdos)
|
. Fix bug #79836 (Segfault in concat_function). (nielsdos)
|
||||||
. Fix bug #81705 (type confusion/UAF on set_error_handler with concat
|
. Fix bug #81705 (type confusion/UAF on set_error_handler with concat
|
||||||
operation). (nielsdos)
|
operation). (nielsdos)
|
||||||
|
. Fix GH-11348 (Closure created from magic method does not accept named
|
||||||
|
arguments). (nielsdos)
|
||||||
|
|
||||||
- Date:
|
- Date:
|
||||||
. Implement More Appropriate Date/Time Exceptions RFC. (Derick)
|
. Implement More Appropriate Date/Time Exceptions RFC. (Derick)
|
||||||
|
|
|
@ -58,6 +58,7 @@ PHP 8.3 UPGRADE NOTES
|
||||||
RFC: https://wiki.php.net/rfc/readonly_amendments
|
RFC: https://wiki.php.net/rfc/readonly_amendments
|
||||||
. Class, interface, trait, and enum constants now support type
|
. Class, interface, trait, and enum constants now support type
|
||||||
declarations. RFC: https://wiki.php.net/rfc/typed_class_constants
|
declarations. RFC: https://wiki.php.net/rfc/typed_class_constants
|
||||||
|
. Closures created from magic methods can now accept named arguments.
|
||||||
|
|
||||||
- Posix
|
- Posix
|
||||||
. posix_getrlimit() now takes an optional $res parameter to allow fetching a
|
. posix_getrlimit() now takes an optional $res parameter to allow fetching a
|
||||||
|
|
112
Zend/tests/trampoline_closure_named_arguments.phpt
Normal file
112
Zend/tests/trampoline_closure_named_arguments.phpt
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
--TEST--
|
||||||
|
Trampoline closure created from magic method accepts named arguments
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public function __call($name, $args) {
|
||||||
|
var_dump($name, $args);
|
||||||
|
}
|
||||||
|
public static function __callStatic($name, $args) {
|
||||||
|
var_dump($name, $args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = new Test;
|
||||||
|
|
||||||
|
echo "-- Non-static cases --\n";
|
||||||
|
$test->test(1, 2, a: 123);
|
||||||
|
$test->test(...)(1, 2);
|
||||||
|
$test->test(...)(1, 2, a: 123, b: $test);
|
||||||
|
$test->test(...)(a: 123, b: $test);
|
||||||
|
$test->test(...)();
|
||||||
|
|
||||||
|
echo "-- Static cases --\n";
|
||||||
|
Test::testStatic(1, 2, a: 123);
|
||||||
|
Test::testStatic(...)(1, 2);
|
||||||
|
Test::testStatic(...)(1, 2, a: 123, b: $test);
|
||||||
|
Test::testStatic(...)(a: 123, b: $test);
|
||||||
|
Test::testStatic(...)();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
-- Non-static cases --
|
||||||
|
string(4) "test"
|
||||||
|
array(3) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
["a"]=>
|
||||||
|
int(123)
|
||||||
|
}
|
||||||
|
string(4) "test"
|
||||||
|
array(2) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
}
|
||||||
|
string(4) "test"
|
||||||
|
array(4) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
["a"]=>
|
||||||
|
int(123)
|
||||||
|
["b"]=>
|
||||||
|
object(Test)#1 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string(4) "test"
|
||||||
|
array(2) {
|
||||||
|
["a"]=>
|
||||||
|
int(123)
|
||||||
|
["b"]=>
|
||||||
|
object(Test)#1 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string(4) "test"
|
||||||
|
array(0) {
|
||||||
|
}
|
||||||
|
-- Static cases --
|
||||||
|
string(10) "testStatic"
|
||||||
|
array(3) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
["a"]=>
|
||||||
|
int(123)
|
||||||
|
}
|
||||||
|
string(10) "testStatic"
|
||||||
|
array(2) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
}
|
||||||
|
string(10) "testStatic"
|
||||||
|
array(4) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
["a"]=>
|
||||||
|
int(123)
|
||||||
|
["b"]=>
|
||||||
|
object(Test)#1 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string(10) "testStatic"
|
||||||
|
array(2) {
|
||||||
|
["a"]=>
|
||||||
|
int(123)
|
||||||
|
["b"]=>
|
||||||
|
object(Test)#1 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string(10) "testStatic"
|
||||||
|
array(0) {
|
||||||
|
}
|
|
@ -294,7 +294,18 @@ static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ {
|
||||||
fci.params = params;
|
fci.params = params;
|
||||||
fci.param_count = 2;
|
fci.param_count = 2;
|
||||||
ZVAL_STR(&fci.params[0], EX(func)->common.function_name);
|
ZVAL_STR(&fci.params[0], EX(func)->common.function_name);
|
||||||
if (ZEND_NUM_ARGS()) {
|
if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||||
|
zend_string *name;
|
||||||
|
zval *named_param_zval;
|
||||||
|
array_init_size(&fci.params[1], ZEND_NUM_ARGS() + zend_hash_num_elements(EX(extra_named_params)));
|
||||||
|
/* Avoid conversion from packed to mixed later. */
|
||||||
|
zend_hash_real_init_mixed(Z_ARRVAL(fci.params[1]));
|
||||||
|
zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]);
|
||||||
|
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, named_param_zval) {
|
||||||
|
Z_TRY_ADDREF_P(named_param_zval);
|
||||||
|
zend_hash_add_new(Z_ARRVAL(fci.params[1]), name, named_param_zval);
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
} else if (ZEND_NUM_ARGS()) {
|
||||||
array_init_size(&fci.params[1], ZEND_NUM_ARGS());
|
array_init_size(&fci.params[1], ZEND_NUM_ARGS());
|
||||||
zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]);
|
zend_copy_parameters_array(ZEND_NUM_ARGS(), &fci.params[1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -841,7 +852,7 @@ void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* {
|
||||||
|
|
||||||
memset(&trampoline, 0, sizeof(zend_internal_function));
|
memset(&trampoline, 0, sizeof(zend_internal_function));
|
||||||
trampoline.type = ZEND_INTERNAL_FUNCTION;
|
trampoline.type = ZEND_INTERNAL_FUNCTION;
|
||||||
trampoline.fn_flags = mptr->common.fn_flags & ZEND_ACC_STATIC;
|
trampoline.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_VARIADIC);
|
||||||
trampoline.handler = zend_closure_call_magic;
|
trampoline.handler = zend_closure_call_magic;
|
||||||
trampoline.function_name = mptr->common.function_name;
|
trampoline.function_name = mptr->common.function_name;
|
||||||
trampoline.scope = mptr->common.scope;
|
trampoline.scope = mptr->common.scope;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue