php-src/Zend/tests/closure_061.phpt
Christoph M. Becker 78773890f6 Fix #74558: Can't rebind closure returned by Closure::fromCallable()
Failure to rebind such closures is not necessarily related to them
being created by `ReflectionFunctionAbstract::getClosure()`, so we fix
the error message.

Closes GH-6424.
2020-11-16 14:31:06 +01:00

244 lines
5.3 KiB
PHP

--TEST--
Rebinding of ::getClosure()s
--FILE--
<?php
use SplDoublyLinkedList as DLL;
function func($arg) { }
class Cls {
public function method() {}
public static function staticMethod($arg) {}
}
class ClsChild extends Cls {}
class ClsUnrelated {}
/* Format: [Function, [Obj, Scope]] */
$tests = [
['func', [
[null, null],
[new Cls, null],
[new Cls, 'Cls'],
[null, 'Cls'],
[null, 'stdClass'],
[new stdClass, null],
]],
['strlen', [
[null, null],
[new Cls, null],
[new Cls, 'Cls'],
[null, 'Cls'],
[null, 'stdClass'],
[new stdClass, null],
]],
[['Cls', 'staticMethod'], [
[null, 'Cls'],
[new Cls, null],
[new Cls, 'Cls'],
[null, null],
[null, 'ClsChild'],
[null, 'ClsUnrelated'],
]],
[[new Cls, 'method'], [
[null, 'Cls'],
[new Cls, 'Cls'],
[new ClsChild, 'Cls'],
[new ClsUnrelated, 'Cls'],
[new Cls, null],
[new Cls, 'ClsUnrelated'],
[new Cls, 'ClsChild'],
]],
[[new DLL, 'count'], [
[new DLL, DLL::class],
[new SplStack, DLL::class],
[new ClsUnrelated, DLL::class],
[null, null],
[null, DLL::class],
[new DLL, null],
[new DLL, ClsUnrelated::class],
]],
[function() {}, [
[null, null],
[new Cls, null],
[new Cls, 'Cls'],
[null, 'Cls'],
[null, 'stdClass'],
[new stdClass, null],
]],
];
set_error_handler(function($errno, $errstr) {
echo "$errstr\n\n";
});
foreach ($tests as list($fn, $bindings)) {
if (is_array($fn)) {
$r = new ReflectionMethod($fn[0], $fn[1]);
$c = $r->getClosure(is_object($fn[0]) ? $fn[0] : null);
$fnStr = is_object($fn[0]) ? "(new " . get_class($fn[0]) . ")->$fn[1]" : "$fn[0]::$fn[1]";
} else {
$c = (new ReflectionFunction($fn))->getClosure();
$fnStr = $fn;
}
if ($fn instanceof Closure) {
$fnStr = "(function() {})";
}
echo "$fnStr()\n" . str_repeat('-', strlen($fnStr) + 2), "\n\n";
foreach ($bindings as list($obj, $scope)) {
$objStr = $obj ? "new " . get_class($obj) : "null";
$scopeStr = $scope ? "$scope::class" : "null";
echo "bindTo($objStr, $scopeStr):\n";
$ret = $c->bindTo($obj, $scope);
if ($ret !== null) {
echo "Success!\n\n";
}
}
}
?>
--EXPECT--
func()
------
bindTo(null, null):
Success!
bindTo(new Cls, null):
Success!
bindTo(new Cls, Cls::class):
Cannot rebind scope of closure created from function
bindTo(null, Cls::class):
Cannot rebind scope of closure created from function
bindTo(null, stdClass::class):
Cannot bind closure to scope of internal class stdClass
bindTo(new stdClass, null):
Success!
strlen()
--------
bindTo(null, null):
Success!
bindTo(new Cls, null):
Success!
bindTo(new Cls, Cls::class):
Cannot rebind scope of closure created from function
bindTo(null, Cls::class):
Cannot rebind scope of closure created from function
bindTo(null, stdClass::class):
Cannot bind closure to scope of internal class stdClass
bindTo(new stdClass, null):
Success!
Cls::staticMethod()
-------------------
bindTo(null, Cls::class):
Success!
bindTo(new Cls, null):
Cannot bind an instance to a static closure
bindTo(new Cls, Cls::class):
Cannot bind an instance to a static closure
bindTo(null, null):
Cannot rebind scope of closure created from method
bindTo(null, ClsChild::class):
Cannot rebind scope of closure created from method
bindTo(null, ClsUnrelated::class):
Cannot rebind scope of closure created from method
(new Cls)->method()
-------------------
bindTo(null, Cls::class):
Unbinding $this of a method is deprecated
Success!
bindTo(new Cls, Cls::class):
Success!
bindTo(new ClsChild, Cls::class):
Success!
bindTo(new ClsUnrelated, Cls::class):
Cannot bind method Cls::method() to object of class ClsUnrelated
bindTo(new Cls, null):
Cannot rebind scope of closure created from method
bindTo(new Cls, ClsUnrelated::class):
Cannot rebind scope of closure created from method
bindTo(new Cls, ClsChild::class):
Cannot rebind scope of closure created from method
(new SplDoublyLinkedList)->count()
----------------------------------
bindTo(new SplDoublyLinkedList, SplDoublyLinkedList::class):
Success!
bindTo(new SplStack, SplDoublyLinkedList::class):
Success!
bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
bindTo(null, null):
Cannot unbind $this of internal method
bindTo(null, SplDoublyLinkedList::class):
Cannot unbind $this of internal method
bindTo(new SplDoublyLinkedList, null):
Cannot rebind scope of closure created from method
bindTo(new SplDoublyLinkedList, ClsUnrelated::class):
Cannot rebind scope of closure created from method
(function() {})()
-----------------
bindTo(null, null):
Success!
bindTo(new Cls, null):
Success!
bindTo(new Cls, Cls::class):
Success!
bindTo(null, Cls::class):
Success!
bindTo(null, stdClass::class):
Cannot bind closure to scope of internal class stdClass
bindTo(new stdClass, null):
Success!