mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: [ci skip] NEWS [ci skip] NEWS Add tests Fix GH-8932: Provide a way to get the called-scope of closures (#9299)
This commit is contained in:
commit
dcde9b85a6
4 changed files with 138 additions and 1 deletions
|
@ -1701,6 +1701,28 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ Returns the called scope associated to the closure */
|
||||||
|
ZEND_METHOD(ReflectionFunctionAbstract, getClosureCalledClass)
|
||||||
|
{
|
||||||
|
reflection_object *intern;
|
||||||
|
|
||||||
|
if (zend_parse_parameters_none() == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
GET_REFLECTION_OBJECT();
|
||||||
|
if (!Z_ISUNDEF(intern->obj)) {
|
||||||
|
zend_class_entry *called_scope;
|
||||||
|
zend_function *closure_func;
|
||||||
|
zend_object *object;
|
||||||
|
if (Z_OBJ_HANDLER(intern->obj, get_closure)
|
||||||
|
&& Z_OBJ_HANDLER(intern->obj, get_closure)(Z_OBJ(intern->obj), &called_scope, &closure_func, &object, 1) == SUCCESS
|
||||||
|
&& closure_func && (called_scope || closure_func->common.scope)) {
|
||||||
|
zend_reflection_class_factory(called_scope ? (zend_class_entry *) called_scope : closure_func->common.scope, return_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Returns an associative array containing the closures lexical scope variables */
|
/* {{{ Returns an associative array containing the closures lexical scope variables */
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, getClosureUsedVariables)
|
ZEND_METHOD(ReflectionFunctionAbstract, getClosureUsedVariables)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,6 +54,9 @@ abstract class ReflectionFunctionAbstract implements Reflector
|
||||||
/** @tentative-return-type */
|
/** @tentative-return-type */
|
||||||
public function getClosureScopeClass(): ?ReflectionClass {}
|
public function getClosureScopeClass(): ?ReflectionClass {}
|
||||||
|
|
||||||
|
/** @tentative-return-type */
|
||||||
|
public function getClosureCalledClass(): ?ReflectionClass {}
|
||||||
|
|
||||||
public function getClosureUsedVariables(): array {}
|
public function getClosureUsedVariables(): array {}
|
||||||
|
|
||||||
/** @tentative-return-type */
|
/** @tentative-return-type */
|
||||||
|
|
6
ext/reflection/php_reflection_arginfo.h
generated
6
ext/reflection/php_reflection_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: 25b36d66ab7fb88b8d44d51e15e530ebff2e1e2c */
|
* Stub hash: a531c9132b4ac3d3196570ae6dda52b8f6a4f488 */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
|
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
|
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
|
||||||
|
@ -31,6 +31,8 @@ ZEND_END_ARG_INFO()
|
||||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass, 0, 0, ReflectionClass, 1)
|
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass, 0, 0, ReflectionClass, 1)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
#define arginfo_class_ReflectionFunctionAbstract_getClosureCalledClass arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getClosureUsedVariables, 0, 0, IS_ARRAY, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getClosureUsedVariables, 0, 0, IS_ARRAY, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
@ -615,6 +617,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, isVariadic);
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, isStatic);
|
ZEND_METHOD(ReflectionFunctionAbstract, isStatic);
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, getClosureThis);
|
ZEND_METHOD(ReflectionFunctionAbstract, getClosureThis);
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass);
|
ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass);
|
||||||
|
ZEND_METHOD(ReflectionFunctionAbstract, getClosureCalledClass);
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, getClosureUsedVariables);
|
ZEND_METHOD(ReflectionFunctionAbstract, getClosureUsedVariables);
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, getDocComment);
|
ZEND_METHOD(ReflectionFunctionAbstract, getDocComment);
|
||||||
ZEND_METHOD(ReflectionFunctionAbstract, getEndLine);
|
ZEND_METHOD(ReflectionFunctionAbstract, getEndLine);
|
||||||
|
@ -861,6 +864,7 @@ static const zend_function_entry class_ReflectionFunctionAbstract_methods[] = {
|
||||||
ZEND_ME(ReflectionFunctionAbstract, isStatic, arginfo_class_ReflectionFunctionAbstract_isStatic, ZEND_ACC_PUBLIC)
|
ZEND_ME(ReflectionFunctionAbstract, isStatic, arginfo_class_ReflectionFunctionAbstract_isStatic, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(ReflectionFunctionAbstract, getClosureThis, arginfo_class_ReflectionFunctionAbstract_getClosureThis, ZEND_ACC_PUBLIC)
|
ZEND_ME(ReflectionFunctionAbstract, getClosureThis, arginfo_class_ReflectionFunctionAbstract_getClosureThis, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(ReflectionFunctionAbstract, getClosureScopeClass, arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass, ZEND_ACC_PUBLIC)
|
ZEND_ME(ReflectionFunctionAbstract, getClosureScopeClass, arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass, ZEND_ACC_PUBLIC)
|
||||||
|
ZEND_ME(ReflectionFunctionAbstract, getClosureCalledClass, arginfo_class_ReflectionFunctionAbstract_getClosureCalledClass, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(ReflectionFunctionAbstract, getClosureUsedVariables, arginfo_class_ReflectionFunctionAbstract_getClosureUsedVariables, ZEND_ACC_PUBLIC)
|
ZEND_ME(ReflectionFunctionAbstract, getClosureUsedVariables, arginfo_class_ReflectionFunctionAbstract_getClosureUsedVariables, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(ReflectionFunctionAbstract, getDocComment, arginfo_class_ReflectionFunctionAbstract_getDocComment, ZEND_ACC_PUBLIC)
|
ZEND_ME(ReflectionFunctionAbstract, getDocComment, arginfo_class_ReflectionFunctionAbstract_getDocComment, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(ReflectionFunctionAbstract, getEndLine, arginfo_class_ReflectionFunctionAbstract_getEndLine, ZEND_ACC_PUBLIC)
|
ZEND_ME(ReflectionFunctionAbstract, getEndLine, arginfo_class_ReflectionFunctionAbstract_getEndLine, ZEND_ACC_PUBLIC)
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
--TEST--
|
||||||
|
GH-8932 (Provide a way to get the called-scope of closures)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class A {
|
||||||
|
public static function __callStatic($name, $args) {
|
||||||
|
echo static::class.'::'.$name, "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __call($name, $args) {
|
||||||
|
echo static::class.'->'.$name, "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function b() {
|
||||||
|
echo static::class.'::b', "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function c() {
|
||||||
|
echo static::class.'->c', "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function makeClosure() {
|
||||||
|
return function () {
|
||||||
|
echo static::class.'::{closure}'."\n";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {}
|
||||||
|
|
||||||
|
$c = ['B', 'b'];
|
||||||
|
$d = \Closure::fromCallable($c);
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
$c = [new B(), 'c'];
|
||||||
|
$d = \Closure::fromCallable($c);
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
$c = ['B', 'd'];
|
||||||
|
$d = \Closure::fromCallable($c);
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
$c = [new B(), 'e'];
|
||||||
|
$d = \Closure::fromCallable($c);
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
$c = ['A', 'b'];
|
||||||
|
$d = \Closure::fromCallable($c);
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
$b = new B();
|
||||||
|
$d = $b->makeClosure();
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
$d = function () {
|
||||||
|
echo "{closure}\n";
|
||||||
|
};
|
||||||
|
$r = new \ReflectionFunction($d);
|
||||||
|
var_dump($r->getClosureCalledClass());
|
||||||
|
$d();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
object(ReflectionClass)#%d (1) {
|
||||||
|
["name"]=>
|
||||||
|
string(1) "B"
|
||||||
|
}
|
||||||
|
B::b
|
||||||
|
object(ReflectionClass)#%d (1) {
|
||||||
|
["name"]=>
|
||||||
|
string(1) "B"
|
||||||
|
}
|
||||||
|
B->c
|
||||||
|
object(ReflectionClass)#%d (1) {
|
||||||
|
["name"]=>
|
||||||
|
string(1) "B"
|
||||||
|
}
|
||||||
|
B::d
|
||||||
|
object(ReflectionClass)#%d (1) {
|
||||||
|
["name"]=>
|
||||||
|
string(1) "B"
|
||||||
|
}
|
||||||
|
B->e
|
||||||
|
object(ReflectionClass)#%d (1) {
|
||||||
|
["name"]=>
|
||||||
|
string(1) "A"
|
||||||
|
}
|
||||||
|
A::b
|
||||||
|
object(ReflectionClass)#%d (1) {
|
||||||
|
["name"]=>
|
||||||
|
string(1) "B"
|
||||||
|
}
|
||||||
|
B::{closure}
|
||||||
|
NULL
|
||||||
|
{closure}
|
Loading…
Add table
Add a link
Reference in a new issue