summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-04-23 17:52:05 +0300
committerDmitry Stogov <dmitry@zend.com>2015-04-23 17:52:05 +0300
commitfc80305e48ac18f643c2ad7e549a3eb8e2454b17 (patch)
tree509e7179cb9ed7fae95a208e35d55095145fcb96
parentea2fc7f935d2767c127756647f47be8d420346ce (diff)
downloadphp-git-fc80305e48ac18f643c2ad7e549a3eb8e2454b17.tar.gz
Cleanup comments and add related tests.
-rw-r--r--Zend/tests/closure_058.phpt64
-rw-r--r--Zend/tests/closure_059.phpt38
-rw-r--r--Zend/zend_closures.c5
3 files changed, 106 insertions, 1 deletions
diff --git a/Zend/tests/closure_058.phpt b/Zend/tests/closure_058.phpt
new file mode 100644
index 0000000000..128661f4fc
--- /dev/null
+++ b/Zend/tests/closure_058.phpt
@@ -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) {
+}
diff --git a/Zend/tests/closure_059.phpt b/Zend/tests/closure_059.phpt
new file mode 100644
index 0000000000..de9c574746
--- /dev/null
+++ b/Zend/tests/closure_059.phpt
@@ -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
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 843254c6ef..952e4ed1e0 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -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);