Cleanup comments and add related tests.

This commit is contained in:
Dmitry Stogov 2015-04-23 17:52:05 +03:00
parent ea2fc7f935
commit fc80305e48
3 changed files with 106 additions and 1 deletions

View file

@ -0,0 +1,64 @@
--TEST--
Closure 058: Closure scope and object
--FILE--
<?php
class A {
static function foo() {
return function () {var_dump(get_class(),get_called_class());};
}
function bar() {
return function () {var_dump(get_class(),get_called_class(),$this);};
}
}
$z = "call_user_func";
$a = A::foo();
$a();
$a->__invoke();
$c = array($a,"__invoke");
$c();
call_user_func(array($a,"__invoke"));
$z(array($a,"__invoke"));
echo "\n";
$x = new A();
$b = $x->bar();
$b();
$b->__invoke();
$c = array($b,"__invoke");
$c();
call_user_func(array($b,"__invoke"));
$z(array($b,"__invoke"));
--EXPECT--
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
object(A)#2 (0) {
}
string(1) "A"
string(1) "A"
object(A)#2 (0) {
}
string(1) "A"
string(1) "A"
object(A)#2 (0) {
}
string(1) "A"
string(1) "A"
object(A)#2 (0) {
}
string(1) "A"
string(1) "A"
object(A)#2 (0) {
}

View file

@ -0,0 +1,38 @@
--TEST--
Closure 059: Closure type hinting
--FILE--
<?php
class A {
}
class B {
}
$a = new A;
$b = new B;
$f = function (A $a){};
$f($a);
$f->__invoke($a);
call_user_func(array($f,"__invoke"), $a);
try {
$f($b);
} catch (EngineException $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
try {
$f->__invoke($b);
} catch (EngineException $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
try {
call_user_func(array($f,"__invoke"), $b);
} catch (EngineException $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
--EXPECTF--
Exception: Argument 1 passed to {closure}() must be an instance of A, instance of B %s
Exception: Argument 1 passed to {closure}() must be an instance of A, instance of B %s
Exception: Argument 1 passed to {closure}() must be an instance of A, instance of B %s

View file

@ -184,7 +184,10 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {
zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
invoke->common = closure->func.common;
/* TODO: return ZEND_INTERNAL_FUNCTION, but arg_info representation is suitable for ZEND_USER_FUNCTION ??? */
/* We return ZEND_INTERNAL_FUNCTION, but arg_info representation is the
* same as for ZEND_USER_FUNCTION (uses zend_string* instead of char*).
* This is not a problem, because ZEND_ACC_HAS_TYPE_HINTS is never set,
* and we won't check arguments on internal function */
invoke->type = ZEND_INTERNAL_FUNCTION;
invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & ZEND_ACC_RETURN_REFERENCE);
invoke->internal_function.handler = ZEND_MN(Closure___invoke);