Skip to content

Commit 0388a13

Browse files
committed
Support __call with named params
1 parent df328f7 commit 0388a13

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

Zend/tests/named_params/__call.phpt

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,30 @@ class Test {
88
$this->{'_'.$method}(...$args);
99
}
1010

11+
public static function __callStatic(string $method, array $args) {
12+
(new static)->{'_'.$method}(...$args);
13+
}
14+
1115
private function _method($a = 'a', $b = 'b') {
1216
echo "a: $a, b: $b\n";
1317
}
1418
}
1519

20+
$obj = new class { public function __toString() { return "STR"; } };
21+
1622
$test = new Test;
17-
$test->method('A', 'B');
1823
$test->method(a: 'A', b: 'B');
24+
$test->method(b: 'B');
25+
$test->method(b: $obj);
26+
Test::method(a: 'A', b: 'B');
27+
Test::method(b: 'B');
28+
Test::method(b: $obj);
1929

2030
?>
21-
--EXPECTF--
31+
--EXPECT--
2232
a: A, b: B
23-
24-
Fatal error: Uncaught Error: Unknown named parameter $a in %s:%d
25-
Stack trace:
26-
#0 {main}
27-
thrown in %s on line %d
33+
a: a, b: B
34+
a: a, b: STR
35+
a: A, b: B
36+
a: a, b: B
37+
a: a, b: STR

Zend/zend_object_handlers.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
11061106
* The low bit must be zero, to not be interpreted as a MAP_PTR offset.
11071107
*/
11081108
static const void *dummy = (void*)(intptr_t)2;
1109+
static const zend_arg_info arg_info[1] = {{0}};
11091110

11101111
ZEND_ASSERT(fbc);
11111112

@@ -1119,7 +1120,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
11191120
func->arg_flags[0] = 0;
11201121
func->arg_flags[1] = 0;
11211122
func->arg_flags[2] = 0;
1122-
func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC;
1123+
func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC | ZEND_ACC_VARIADIC;
11231124
if (is_static) {
11241125
func->fn_flags |= ZEND_ACC_STATIC;
11251126
}
@@ -1143,7 +1144,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
11431144
func->prototype = NULL;
11441145
func->num_args = 0;
11451146
func->required_num_args = 0;
1146-
func->arg_info = 0;
1147+
func->arg_info = (zend_arg_info *) arg_info;
11471148

11481149
return (zend_function*)func;
11491150
}

Zend/zend_vm_def.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8292,7 +8292,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
82928292
zend_array *args = NULL;
82938293
zend_function *fbc = EX(func);
82948294
zval *ret = EX(return_value);
8295-
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS);
8295+
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
82968296
uint32_t num_args = EX_NUM_ARGS();
82978297
zend_execute_data *call;
82988298

@@ -8325,6 +8325,10 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
83258325
} else {
83268326
ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2));
83278327
}
8328+
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
8329+
SEPARATE_ARRAY(ZEND_CALL_ARG(call, 2));
8330+
zend_hash_copy(Z_ARRVAL_P(ZEND_CALL_ARG(call, 2)), call->extra_named_params, zval_add_ref);
8331+
}
83288332
zend_free_trampoline(fbc);
83298333
fbc = call->func;
83308334

Zend/zend_vm_execute.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2810,7 +2810,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
28102810
zend_array *args = NULL;
28112811
zend_function *fbc = EX(func);
28122812
zval *ret = EX(return_value);
2813-
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS);
2813+
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
28142814
uint32_t num_args = EX_NUM_ARGS();
28152815
zend_execute_data *call;
28162816

@@ -2843,6 +2843,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
28432843
} else {
28442844
ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2));
28452845
}
2846+
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
2847+
SEPARATE_ARRAY(ZEND_CALL_ARG(call, 2));
2848+
zend_hash_copy(Z_ARRVAL_P(ZEND_CALL_ARG(call, 2)), call->extra_named_params, zval_add_ref);
2849+
}
28462850
zend_free_trampoline(fbc);
28472851
fbc = call->func;
28482852

0 commit comments

Comments
 (0)