From: Dmitry Stogov Date: Mon, 14 Jul 2008 12:18:23 +0000 (+0000) Subject: Fixed is_callable() to support closures and return appropriate function name X-Git-Tag: php-5.3.0alpha1~352 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0fa7fedfde33e7fd50fe935d4951caaad35b4241;p=php Fixed is_callable() to support closures and return appropriate function name --- 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 68f0c7880c..358feff3c9 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2619,8 +2619,12 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** case IS_OBJECT: if (zend_get_closure(callable, ce_ptr, fptr_ptr, NULL, zobj_ptr_ptr TSRMLS_CC) == SUCCESS) { if (callable_name) { - *callable_name_len = strlen((*fptr_ptr)->common.function_name); - *callable_name = estrndup((*fptr_ptr)->common.function_name, *callable_name_len); + zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */ + + *callable_name_len = ce->name_length + sizeof("::__invoke") - 1; + *callable_name = emalloc(*callable_name_len + 1); + memcpy(*callable_name, ce->name, ce->name_length); + memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke")); } return 1; } diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 5ed979cc62..30187a8fc7 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"); @@ -181,7 +187,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 5546e2a0da..7a8a2c3af4 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1409,7 +1409,7 @@ void zend_do_begin_lambda_function_declaration(znode *result, znode *function_to zend_op *current_op; function_name.op_type = IS_CONST; - ZVAL_STRINGL(&function_name.u.constant, "lambda", sizeof("lambda")-1, 1); + ZVAL_STRINGL(&function_name.u.constant, "", sizeof("")-1, 1); zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a907f50146..6c35cd9b5d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4339,7 +4339,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, CONST) { zend_op *opline = EX(opline); - zend_op_array *op_array; + zend_function *op_array; if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), Z_LVAL(opline->op2.u.constant), (void *) &op_array) == FAILURE || op_array->type != ZEND_USER_FUNCTION) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3026f4555b..d928c1ae26 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2914,7 +2914,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_op_array *op_array; + zend_function *op_array; if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), Z_LVAL(opline->op2.u.constant), (void *) &op_array) == FAILURE || op_array->type != ZEND_USER_FUNCTION) {