--- /dev/null
+--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) {
+}
--- /dev/null
+--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
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);