Skip to content

Commit 41bec20

Browse files
committed
Support __call with named params
1 parent 1a8bfef commit 41bec20

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
@@ -8289,7 +8289,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
82898289
zend_array *args = NULL;
82908290
zend_function *fbc = EX(func);
82918291
zval *ret = EX(return_value);
8292-
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS);
8292+
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
82938293
uint32_t num_args = EX_NUM_ARGS();
82948294
zend_execute_data *call;
82958295

@@ -8322,6 +8322,10 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
83228322
} else {
83238323
ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2));
83248324
}
8325+
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
8326+
SEPARATE_ARRAY(ZEND_CALL_ARG(call, 2));
8327+
zend_hash_copy(Z_ARRVAL_P(ZEND_CALL_ARG(call, 2)), call->extra_named_params, zval_add_ref);
8328+
}
83258329
zend_free_trampoline(fbc);
83268330
fbc = call->func;
83278331

Zend/zend_vm_execute.h

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

@@ -2841,6 +2841,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
28412841
} else {
28422842
ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2));
28432843
}
2844+
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
2845+
SEPARATE_ARRAY(ZEND_CALL_ARG(call, 2));
2846+
zend_hash_copy(Z_ARRVAL_P(ZEND_CALL_ARG(call, 2)), call->extra_named_params, zval_add_ref);
2847+
}
28442848
zend_free_trampoline(fbc);
28452849
fbc = call->func;
28462850

0 commit comments

Comments
 (0)