diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-09-21 14:45:31 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-09-21 14:46:10 +0200 |
commit | 8e0789a21c3218efbb58417b45a7c36649a606d6 (patch) | |
tree | 191351628e00e130e6335c64170a9e8bc622ebc6 | |
parent | 4c821cf20668776737272587e7a87876b4fca25e (diff) | |
download | php-git-8e0789a21c3218efbb58417b45a7c36649a606d6.tar.gz |
Use proper parameter type in Closure::bindTo() signature
-rw-r--r-- | Zend/tests/closure_040.phpt | 10 | ||||
-rw-r--r-- | Zend/zend_closures.c | 63 | ||||
-rw-r--r-- | Zend/zend_closures.stub.php | 10 | ||||
-rw-r--r-- | Zend/zend_closures_arginfo.h | 6 |
4 files changed, 47 insertions, 42 deletions
diff --git a/Zend/tests/closure_040.phpt b/Zend/tests/closure_040.phpt index a18ae2640e..436c99939b 100644 --- a/Zend/tests/closure_040.phpt +++ b/Zend/tests/closure_040.phpt @@ -24,14 +24,16 @@ $a = new A(20); $ca = $a->getIncrementor(); $cas = $a->getStaticIncrementor(); -$ca->bindTo($a, array()); +try { + $ca->bindTo($a, array()); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} $cas->bindTo($a, 'A'); ?> --EXPECTF-- -Warning: Array to string conversion in %s on line %d - -Warning: Class "Array" not found in %s on line %d +Closure::bindTo(): Argument #2 ($newScope) must be of type object|string|null, array given Warning: Cannot bind an instance to a static closure in %s on line %d diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 86cabf0a10..034b0d2d07 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -192,30 +192,22 @@ ZEND_METHOD(Closure, call) } /* }}} */ -static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, zval *scope_arg) +static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, zend_object *scope_obj, zend_string *scope_str) { zend_class_entry *ce, *called_scope; zend_closure *closure = (zend_closure *) Z_OBJ_P(zclosure); - if (scope_arg != NULL) { /* scope argument was given */ - if (Z_TYPE_P(scope_arg) == IS_OBJECT) { - ce = Z_OBJCE_P(scope_arg); - } else if (Z_TYPE_P(scope_arg) == IS_NULL) { - ce = NULL; - } else { - zend_string *tmp_class_name; - zend_string *class_name = zval_get_tmp_string(scope_arg, &tmp_class_name); - if (zend_string_equals_literal(class_name, "static")) { - ce = closure->func.common.scope; - } else if ((ce = zend_lookup_class(class_name)) == NULL) { - zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(class_name)); - zend_tmp_string_release(tmp_class_name); - RETURN_NULL(); - } - zend_tmp_string_release(tmp_class_name); + if (scope_obj) { + ce = scope_obj->ce; + } else if (scope_str) { + if (zend_string_equals(scope_str, ZSTR_KNOWN(ZEND_STR_STATIC))) { + ce = closure->func.common.scope; + } else if ((ce = zend_lookup_class(scope_str)) == NULL) { + zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(scope_str)); + RETURN_NULL(); } - } else { /* scope argument not given; do not change the scope by default */ - ce = closure->func.common.scope; + } else { + ce = NULL; } if (!zend_valid_closure_binding(closure, newthis, ce)) { @@ -234,25 +226,34 @@ static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, z /* {{{ Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) { - zval *newthis, *zclosure, *scope_arg = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { - RETURN_THROWS(); - } + zval *zclosure, *newthis; + zend_object *scope_obj = NULL; + zend_string *scope_str = ZSTR_KNOWN(ZEND_STR_STATIC); + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_OBJECT_OF_CLASS(zclosure, zend_ce_closure) + Z_PARAM_OBJECT_OR_NULL(newthis) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OR_STR_OR_NULL(scope_obj, scope_str) + ZEND_PARSE_PARAMETERS_END(); - do_closure_bind(return_value, zclosure, newthis, scope_arg); + do_closure_bind(return_value, zclosure, newthis, scope_obj, scope_str); } /* {{{ Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bindTo) { - zval *newthis, *scope_arg = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!|z", &newthis, &scope_arg) == FAILURE) { - RETURN_THROWS(); - } + zval *newthis; + zend_object *scope_obj = NULL; + zend_string *scope_str = ZSTR_KNOWN(ZEND_STR_STATIC); + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_OBJECT_OR_NULL(newthis) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OR_STR_OR_NULL(scope_obj, scope_str) + ZEND_PARSE_PARAMETERS_END(); - do_closure_bind(return_value, getThis(), newthis, scope_arg); + do_closure_bind(return_value, getThis(), newthis, scope_obj, scope_str); } static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ { diff --git a/Zend/zend_closures.stub.php b/Zend/zend_closures.stub.php index 70e555bff2..875ee69203 100644 --- a/Zend/zend_closures.stub.php +++ b/Zend/zend_closures.stub.php @@ -6,11 +6,13 @@ final class Closure { private function __construct() {} - /** @param object|string|null $newScope */ - public static function bind(Closure $closure, ?object $newThis, $newScope = UNKNOWN): ?Closure {} + public static function bind( + Closure $closure, + ?object $newThis, + object|string|null $newScope = "static" + ): ?Closure {} - /** @param object|string|null $newScope */ - public function bindTo(?object $newThis, $newScope = UNKNOWN): ?Closure {} + public function bindTo(?object $newThis, object|string|null $newScope = "static"): ?Closure {} public function call(object $newThis, mixed ...$arguments): mixed {} diff --git a/Zend/zend_closures_arginfo.h b/Zend/zend_closures_arginfo.h index f09023b132..1a01ab2810 100644 --- a/Zend/zend_closures_arginfo.h +++ b/Zend/zend_closures_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: abbbe7b04323dc44b0675ad58700e996a6d7c43b */ + * Stub hash: 6c9840dd5c2e4c597cd0133bf2d0b523c272d3fe */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -7,12 +7,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Closure_bind, 0, 2, Closure, 1) ZEND_ARG_OBJ_INFO(0, closure, Closure, 0) ZEND_ARG_TYPE_INFO(0, newThis, IS_OBJECT, 1) - ZEND_ARG_INFO(0, newScope) + ZEND_ARG_TYPE_MASK(0, newScope, MAY_BE_OBJECT|MAY_BE_STRING|MAY_BE_NULL, "\"static\"") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Closure_bindTo, 0, 1, Closure, 1) ZEND_ARG_TYPE_INFO(0, newThis, IS_OBJECT, 1) - ZEND_ARG_INFO(0, newScope) + ZEND_ARG_TYPE_MASK(0, newScope, MAY_BE_OBJECT|MAY_BE_STRING|MAY_BE_NULL, "\"static\"") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Closure_call, 0, 1, IS_MIXED, 0) |