From 84625f5e7e02b935b68bcb180839fef6c80df491 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 14 Jul 2008 12:17:16 +0000 Subject: [PATCH] Fixed is_callable() to support closures and return appropriate function name --- Zend/tests/closure_016.phpt | 51 +++++++++++++++++++++++++++++++++++++ Zend/zend_API.c | 16 +++++++++++- Zend/zend_closures.c | 8 +++++- Zend/zend_compile.c | 2 +- 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100755 Zend/tests/closure_016.phpt diff --git a/Zend/tests/closure_016.phpt b/Zend/tests/closure_016.phpt new file mode 100755 index 0000000000..ae0036586c --- /dev/null +++ b/Zend/tests/closure_016.phpt @@ -0,0 +1,51 @@ +--TEST-- +Closure 016: closures and is_callable() +--FILE-- + +--EXPECT-- +bool(true) +Foo::__invoke +bool(true) +Foo::__invoke +bool(true) +Foo::__invoke +bool(true) +Foo::__invoke +bool(true) +Closure::__invoke +bool(true) +Closure::__invoke +bool(true) +Closure::__invoke +bool(true) +Closure::__invoke diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 4ea1abbf1e..a8a0486d71 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3097,7 +3097,21 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, zval *c case IS_OBJECT: if (zend_get_closure(callable, ce_ptr, fptr_ptr, NULL, zobj_ptr_ptr TSRMLS_CC) == SUCCESS) { if (callable_name) { - ZVAL_ZSTR(callable_name, UG(unicode) ? IS_UNICODE : IS_STRING, (*fptr_ptr)->common.function_name, 1); + zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */ + + if (UG(unicode)) { + Z_TYPE_P(callable_name) = IS_UNICODE; + Z_USTRLEN_P(callable_name) = ce->name_length + sizeof("::__invoke") - 1; + Z_USTRVAL_P(callable_name) = eumalloc(Z_USTRLEN_P(callable_name)+1); + u_memcpy(Z_USTRVAL_P(callable_name), ce->name.u, ce->name_length); + u_charsToUChars("::__invoke", Z_USTRVAL_P(callable_name) + ce->name_length, sizeof("::__invoke")); + } else { + Z_TYPE_P(callable_name) = IS_STRING; + Z_STRLEN_P(callable_name) = ce->name_length + sizeof("::__invoke") - 1; + Z_STRVAL_P(callable_name) = emalloc(Z_STRLEN_P(callable_name) + 1); + memcpy(Z_STRVAL_P(callable_name), ce->name.s, ce->name_length); + memcpy(Z_STRVAL_P(callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke")); + } } return 1; } diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 64a74bcd32..fd9b4ddcb0 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -70,6 +70,12 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */ } /* }}} */ +const static zend_function_entry closure_functions[] = { /* {{{ */ + ZEND_ME(Closure, __invoke, NULL, 0) + {NULL, NULL, NULL} +}; +/* }}} */ + static zend_function *zend_closure_get_constructor(zval *object TSRMLS_DC) /* {{{ */ { zend_error(E_ERROR, "Instantiation of 'Closure' is not allowed"); @@ -193,7 +199,7 @@ void zend_register_closure_ce(TSRMLS_D) /* {{{ */ { zend_class_entry ce; - INIT_CLASS_ENTRY(ce, "Closure", NULL); + INIT_CLASS_ENTRY(ce, "Closure", closure_functions); zend_ce_closure = zend_register_internal_class(&ce TSRMLS_CC); zend_ce_closure->ce_flags |= ZEND_ACC_FINAL_CLASS; zend_ce_closure->create_object = zend_closure_new; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index dd2d49ba79..3020be645d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1482,7 +1482,7 @@ void zend_do_begin_lambda_function_declaration(znode *result, znode *function_to zend_op *current_op; function_name.op_type = IS_CONST; - ZVAL_ASCII_STRING(&function_name.u.constant, "lambda", ZSTR_DUPLICATE); + ZVAL_ASCII_STRING(&function_name.u.constant, "", ZSTR_DUPLICATE); zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC); -- 2.50.1