mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
[DOC] Remove $this support in closures for PHP 5.3 beta 1
- Implementation notes here: http://wiki.php.net/rfc/closures/removal-of-this
This commit is contained in:
parent
7cb513c19a
commit
c6d89bd4a8
22 changed files with 113 additions and 693 deletions
|
@ -1,74 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Closure 005: Lambda inside class, lifetime of $this
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
class A {
|
|
||||||
private $x;
|
|
||||||
|
|
||||||
function __construct($x) {
|
|
||||||
$this->x = $x;
|
|
||||||
}
|
|
||||||
|
|
||||||
function __destruct() {
|
|
||||||
echo "Destroyed\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
function getIncer($val) {
|
|
||||||
return function() use ($val) {
|
|
||||||
$this->x += $val;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrinter() {
|
|
||||||
return function() {
|
|
||||||
echo $this->x."\n";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getError() {
|
|
||||||
return static function() {
|
|
||||||
echo $this->x."\n";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function printX() {
|
|
||||||
echo $this->x."\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$a = new A(3);
|
|
||||||
$incer = $a->getIncer(2);
|
|
||||||
$printer = $a->getPrinter();
|
|
||||||
$error = $a->getError();
|
|
||||||
|
|
||||||
$a->printX();
|
|
||||||
$printer();
|
|
||||||
$incer();
|
|
||||||
$a->printX();
|
|
||||||
$printer();
|
|
||||||
|
|
||||||
unset($a);
|
|
||||||
|
|
||||||
$incer();
|
|
||||||
$printer();
|
|
||||||
|
|
||||||
unset($incer);
|
|
||||||
$printer();
|
|
||||||
|
|
||||||
unset($printer);
|
|
||||||
|
|
||||||
$error();
|
|
||||||
|
|
||||||
echo "Done\n";
|
|
||||||
?>
|
|
||||||
--EXPECTF--
|
|
||||||
3
|
|
||||||
3
|
|
||||||
5
|
|
||||||
5
|
|
||||||
7
|
|
||||||
7
|
|
||||||
Destroyed
|
|
||||||
|
|
||||||
Fatal error: Using $this when not in object context in %sclosure_005.php on line 28
|
|
|
@ -1,38 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Closure 007: Nested lambdas in classes
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
class A {
|
|
||||||
private $x = 0;
|
|
||||||
|
|
||||||
function getClosureGetter () {
|
|
||||||
return function () {
|
|
||||||
return function () {
|
|
||||||
$this->x++;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function printX () {
|
|
||||||
echo $this->x."\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$a = new A;
|
|
||||||
$a->printX();
|
|
||||||
$getClosure = $a->getClosureGetter();
|
|
||||||
$a->printX();
|
|
||||||
$closure = $getClosure();
|
|
||||||
$a->printX();
|
|
||||||
$closure();
|
|
||||||
$a->printX();
|
|
||||||
|
|
||||||
echo "Done\n";
|
|
||||||
?>
|
|
||||||
--EXPECT--
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
1
|
|
||||||
Done
|
|
|
@ -27,22 +27,7 @@ object(foo)#%d (%d) {
|
||||||
["test":"foo":private]=>
|
["test":"foo":private]=>
|
||||||
int(3)
|
int(3)
|
||||||
["a"]=>
|
["a"]=>
|
||||||
object(Closure)#%d (2) {
|
object(Closure)#%d (1) {
|
||||||
["this"]=>
|
|
||||||
object(foo)#%d (2) {
|
|
||||||
["test":"foo":private]=>
|
|
||||||
int(3)
|
|
||||||
["a"]=>
|
|
||||||
object(Closure)#%d (2) {
|
|
||||||
["this"]=>
|
|
||||||
*RECURSION*
|
|
||||||
["static"]=>
|
|
||||||
array(1) {
|
|
||||||
["a"]=>
|
|
||||||
*RECURSION*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
["static"]=>
|
["static"]=>
|
||||||
array(1) {
|
array(1) {
|
||||||
["a"]=>
|
["a"]=>
|
||||||
|
@ -50,9 +35,7 @@ object(foo)#%d (%d) {
|
||||||
["test":"foo":private]=>
|
["test":"foo":private]=>
|
||||||
int(3)
|
int(3)
|
||||||
["a"]=>
|
["a"]=>
|
||||||
object(Closure)#%d (2) {
|
object(Closure)#%d (1) {
|
||||||
["this"]=>
|
|
||||||
*RECURSION*
|
|
||||||
["static"]=>
|
["static"]=>
|
||||||
array(1) {
|
array(1) {
|
||||||
["a"]=>
|
["a"]=>
|
||||||
|
|
|
@ -32,18 +32,7 @@ object(foo)#%d (1) {
|
||||||
["a"]=>
|
["a"]=>
|
||||||
array(1) {
|
array(1) {
|
||||||
[0]=>
|
[0]=>
|
||||||
object(Closure)#%d (1) {
|
object(Closure)#%d (0) {
|
||||||
["this"]=>
|
|
||||||
object(foo)#%d (1) {
|
|
||||||
["a"]=>
|
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
object(Closure)#%d (1) {
|
|
||||||
["this"]=>
|
|
||||||
*RECURSION*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,21 +41,7 @@ int(1)
|
||||||
string(1) "a"
|
string(1) "a"
|
||||||
array(1) {
|
array(1) {
|
||||||
[0]=>
|
[0]=>
|
||||||
object(Closure)#%d (1) {
|
object(Closure)#%d (0) {
|
||||||
["this"]=>
|
|
||||||
object(foo)#%d (1) {
|
|
||||||
["a"]=>
|
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
object(Closure)#%d (1) {
|
|
||||||
["this"]=>
|
|
||||||
object(foo)#%d (1) {
|
|
||||||
["a"]=>
|
|
||||||
*RECURSION*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int(1)
|
int(1)
|
||||||
|
|
|
@ -53,7 +53,6 @@ Array
|
||||||
(
|
(
|
||||||
[0] => Closure Object
|
[0] => Closure Object
|
||||||
(
|
(
|
||||||
[this] =>
|
|
||||||
[parameter] => Array
|
[parameter] => Array
|
||||||
(
|
(
|
||||||
[$param] => <required>
|
[$param] => <required>
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
typedef struct _zend_closure {
|
typedef struct _zend_closure {
|
||||||
zend_object std;
|
zend_object std;
|
||||||
zend_function func;
|
zend_function func;
|
||||||
zval *this_ptr;
|
|
||||||
} zend_closure;
|
} zend_closure;
|
||||||
|
|
||||||
/* non-static since it needs to be referenced */
|
/* non-static since it needs to be referenced */
|
||||||
|
@ -111,13 +110,6 @@ ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC) /
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC) /* {{{ */
|
|
||||||
{
|
|
||||||
zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
|
||||||
return closure->this_ptr;
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */
|
static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
char *lc_name;
|
char *lc_name;
|
||||||
|
@ -187,10 +179,6 @@ static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
|
||||||
destroy_op_array(&closure->func.op_array TSRMLS_CC);
|
destroy_op_array(&closure->func.op_array TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closure->this_ptr) {
|
|
||||||
zval_ptr_dtor(&closure->this_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
efree(closure);
|
efree(closure);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -223,17 +211,10 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function
|
||||||
closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
|
||||||
*fptr_ptr = &closure->func;
|
*fptr_ptr = &closure->func;
|
||||||
|
|
||||||
if (closure->this_ptr) {
|
if (zobj_ptr) {
|
||||||
if (zobj_ptr) {
|
*zobj_ptr = NULL;
|
||||||
*zobj_ptr = closure->this_ptr;
|
|
||||||
}
|
|
||||||
*ce_ptr = Z_OBJCE_P(closure->this_ptr);
|
|
||||||
} else {
|
|
||||||
if (zobj_ptr) {
|
|
||||||
*zobj_ptr = NULL;
|
|
||||||
}
|
|
||||||
*ce_ptr = closure->func.common.scope;
|
|
||||||
}
|
}
|
||||||
|
*ce_ptr = NULL;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -248,13 +229,6 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
|
||||||
*is_temp = 1;
|
*is_temp = 1;
|
||||||
ALLOC_HASHTABLE(rv);
|
ALLOC_HASHTABLE(rv);
|
||||||
zend_hash_init(rv, 1, NULL, ZVAL_PTR_DTOR, 0);
|
zend_hash_init(rv, 1, NULL, ZVAL_PTR_DTOR, 0);
|
||||||
val = closure->this_ptr;
|
|
||||||
if (!val) {
|
|
||||||
ALLOC_INIT_ZVAL(val);
|
|
||||||
} else {
|
|
||||||
Z_ADDREF_P(val);
|
|
||||||
}
|
|
||||||
zend_symtable_update(rv, "this", sizeof("this"), (void *) &val, sizeof(zval *), NULL);
|
|
||||||
if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
|
if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
|
||||||
HashTable *static_variables = closure->func.op_array.static_variables;
|
HashTable *static_variables = closure->func.op_array.static_variables;
|
||||||
MAKE_STD_ZVAL(val);
|
MAKE_STD_ZVAL(val);
|
||||||
|
@ -369,7 +343,7 @@ static int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args,
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zval *this_ptr TSRMLS_DC) /* {{{ */
|
ZEND_API void zend_create_closure(zval *res, zend_function *func TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_closure *closure;
|
zend_closure *closure;
|
||||||
|
|
||||||
|
@ -390,19 +364,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
|
||||||
(*closure->func.op_array.refcount)++;
|
(*closure->func.op_array.refcount)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
closure->func.common.scope = scope;
|
closure->func.common.scope = NULL;
|
||||||
if (scope) {
|
|
||||||
closure->func.common.fn_flags |= ZEND_ACC_PUBLIC;
|
|
||||||
if (this_ptr && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) {
|
|
||||||
closure->this_ptr = this_ptr;
|
|
||||||
Z_ADDREF_P(this_ptr);
|
|
||||||
} else {
|
|
||||||
closure->func.common.fn_flags |= ZEND_ACC_STATIC;
|
|
||||||
closure->this_ptr = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
closure->this_ptr = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,9 @@ void zend_register_closure_ce(TSRMLS_D);
|
||||||
|
|
||||||
extern ZEND_API zend_class_entry *zend_ce_closure;
|
extern ZEND_API zend_class_entry *zend_ce_closure;
|
||||||
|
|
||||||
ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zval *this_ptr TSRMLS_DC);
|
ZEND_API void zend_create_closure(zval *res, zend_function *op_array TSRMLS_DC);
|
||||||
ZEND_API int zend_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr, zval ***zobj_ptr_ptr TSRMLS_DC);
|
|
||||||
ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC);
|
ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC);
|
||||||
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC);
|
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC);
|
||||||
ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC);
|
|
||||||
|
|
||||||
END_EXTERN_C()
|
END_EXTERN_C()
|
||||||
|
|
||||||
|
|
|
@ -1389,7 +1389,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
|
||||||
CG(labels) = NULL;
|
CG(labels) = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC)
|
void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC)
|
||||||
{
|
{
|
||||||
znode function_name;
|
znode function_name;
|
||||||
zend_op_array *current_op_array = CG(active_op_array);
|
zend_op_array *current_op_array = CG(active_op_array);
|
||||||
|
@ -1409,9 +1409,6 @@ void zend_do_begin_lambda_function_declaration(znode *result, znode *function_to
|
||||||
zval_dtor(¤t_op->op2.u.constant);
|
zval_dtor(¤t_op->op2.u.constant);
|
||||||
ZVAL_LONG(¤t_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant)));
|
ZVAL_LONG(¤t_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant)));
|
||||||
current_op->result = *result;
|
current_op->result = *result;
|
||||||
if (is_static) {
|
|
||||||
CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
|
|
||||||
}
|
|
||||||
CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
|
CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,7 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
|
||||||
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
|
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
|
||||||
void zend_do_handle_exception(TSRMLS_D);
|
void zend_do_handle_exception(TSRMLS_D);
|
||||||
|
|
||||||
void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC);
|
void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC);
|
||||||
void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC);
|
void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC);
|
||||||
|
|
||||||
void zend_do_try(znode *try_token TSRMLS_DC);
|
void zend_do_try(znode *try_token TSRMLS_DC);
|
||||||
|
|
|
@ -647,10 +647,8 @@ expr_without_variable:
|
||||||
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
|
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
|
||||||
| '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
|
| '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
|
||||||
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
|
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
|
||||||
| function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
|
| function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type TSRMLS_CC); }
|
||||||
parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
|
parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
|
||||||
| T_STATIC function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); }
|
|
||||||
parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $5; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
function:
|
function:
|
||||||
|
|
|
@ -4393,7 +4393,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, CONST)
|
||||||
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
|
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_create_closure(&EX_T(opline->result.u.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC);
|
zend_create_closure(&EX_T(opline->result.u.var).tmp_var, op_array TSRMLS_CC);
|
||||||
|
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2912,7 +2912,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_CONST_HANDLER(
|
||||||
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
|
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_create_closure(&EX_T(opline->result.u.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC);
|
zend_create_closure(&EX_T(opline->result.u.var).tmp_var, op_array TSRMLS_CC);
|
||||||
|
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,7 +326,7 @@ static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC);
|
static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC);
|
||||||
static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, zval* prop_name, zval* closure, char *indent TSRMLS_DC);
|
static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char *indent TSRMLS_DC);
|
||||||
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC);
|
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC);
|
||||||
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
|
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
|
||||||
static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
|
static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
|
||||||
|
@ -492,7 +492,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
|
||||||
&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
|
&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
|
||||||
{
|
{
|
||||||
string_printf(str, "\n");
|
string_printf(str, "\n");
|
||||||
_function_string(str, mptr, ce, NULL, NULL, sub_indent.string TSRMLS_CC);
|
_function_string(str, mptr, ce, sub_indent.string TSRMLS_CC);
|
||||||
}
|
}
|
||||||
zend_hash_move_forward_ex(&ce->function_table, &pos);
|
zend_hash_move_forward_ex(&ce->function_table, &pos);
|
||||||
}
|
}
|
||||||
|
@ -594,7 +594,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
|
||||||
closure = NULL;
|
closure = NULL;
|
||||||
}
|
}
|
||||||
string_printf(&dyn, "\n");
|
string_printf(&dyn, "\n");
|
||||||
_function_string(&dyn, mptr, ce, NULL, NULL, sub_indent.string TSRMLS_CC);
|
_function_string(&dyn, mptr, ce, sub_indent.string TSRMLS_CC);
|
||||||
count++;
|
count++;
|
||||||
_free_function(closure TSRMLS_CC);
|
_free_function(closure TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
@ -750,8 +750,42 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ _function_closure_string */
|
||||||
|
static void _function_closure_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
|
||||||
|
{
|
||||||
|
zend_uint i, count;
|
||||||
|
ulong num_index;
|
||||||
|
char *key;
|
||||||
|
uint key_len;
|
||||||
|
HashTable *static_variables;
|
||||||
|
HashPosition pos;
|
||||||
|
|
||||||
|
if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_variables = fptr->op_array.static_variables;
|
||||||
|
count = zend_hash_num_elements(static_variables);
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_printf(str, "\n");
|
||||||
|
string_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
|
||||||
|
zend_hash_internal_pointer_reset_ex(static_variables, &pos);
|
||||||
|
i = 0;
|
||||||
|
while (i < count) {
|
||||||
|
zend_hash_get_current_key_ex(static_variables, &key, &key_len, &num_index, 0, &pos);
|
||||||
|
string_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, key);
|
||||||
|
zend_hash_move_forward_ex(static_variables, &pos);
|
||||||
|
}
|
||||||
|
string_printf(str, "%s}\n", indent);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ _function_string */
|
/* {{{ _function_string */
|
||||||
static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, zval* prop_name, zval* closure, char* indent TSRMLS_DC)
|
static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent TSRMLS_DC)
|
||||||
{
|
{
|
||||||
string param_indent;
|
string param_indent;
|
||||||
zend_function *overwrites;
|
zend_function *overwrites;
|
||||||
|
@ -767,7 +801,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
|
||||||
}
|
}
|
||||||
|
|
||||||
string_write(str, indent, strlen(indent));
|
string_write(str, indent, strlen(indent));
|
||||||
string_printf(str, closure ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
|
string_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
|
||||||
string_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
|
string_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
|
||||||
if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||||
string_printf(str, ", deprecated");
|
string_printf(str, ", deprecated");
|
||||||
|
@ -835,7 +869,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
|
||||||
if (fptr->op_array.return_reference) {
|
if (fptr->op_array.return_reference) {
|
||||||
string_printf(str, "&");
|
string_printf(str, "&");
|
||||||
}
|
}
|
||||||
string_printf(str, "%s ] {\n", closure && prop_name ? Z_STRVAL_P(prop_name) : fptr->common.function_name);
|
string_printf(str, "%s ] {\n", fptr->common.function_name);
|
||||||
/* The information where a function is declared is only available for user classes */
|
/* The information where a function is declared is only available for user classes */
|
||||||
if (fptr->type == ZEND_USER_FUNCTION) {
|
if (fptr->type == ZEND_USER_FUNCTION) {
|
||||||
string_printf(str, "%s @@ %s %d - %d\n", indent,
|
string_printf(str, "%s @@ %s %d - %d\n", indent,
|
||||||
|
@ -843,38 +877,11 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
|
||||||
fptr->op_array.line_start,
|
fptr->op_array.line_start,
|
||||||
fptr->op_array.line_end);
|
fptr->op_array.line_end);
|
||||||
}
|
}
|
||||||
if (closure) {
|
|
||||||
const zend_function *closure_fptr = zend_get_closure_method_def(closure TSRMLS_CC);
|
|
||||||
zval *closure_this = zend_get_closure_this_ptr(closure TSRMLS_CC);
|
|
||||||
HashTable *static_variables = NULL;
|
|
||||||
int index = 0, count = closure_this ? 1 : 0;
|
|
||||||
if (closure_fptr->type == ZEND_USER_FUNCTION && closure_fptr->op_array.static_variables) {
|
|
||||||
static_variables = closure_fptr->op_array.static_variables;
|
|
||||||
count += zend_hash_num_elements(static_variables);
|
|
||||||
}
|
|
||||||
if (count) {
|
|
||||||
string_printf(str, "\n");
|
|
||||||
string_printf(str, "%s - Static Parameters [%d] {\n", indent, count);
|
|
||||||
if (closure_this) {
|
|
||||||
string_printf(str, "%s Parameter #%d [ %s $this ]\n", indent, index++, Z_OBJCE_P(closure_this)->name);
|
|
||||||
}
|
|
||||||
if (static_variables) {
|
|
||||||
HashPosition pos;
|
|
||||||
uint key_len;
|
|
||||||
char* key;
|
|
||||||
ulong num_index;
|
|
||||||
zend_hash_internal_pointer_reset_ex(static_variables, &pos);
|
|
||||||
while (index < count) {
|
|
||||||
zend_hash_get_current_key_ex(static_variables, &key, &key_len, &num_index, 0, &pos);
|
|
||||||
string_printf(str, "%s Parameter #%d [ $%s ]\n", indent, index++, key);
|
|
||||||
zend_hash_move_forward_ex(static_variables, &pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
string_printf(str, "%s }\n", indent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
string_init(¶m_indent);
|
string_init(¶m_indent);
|
||||||
string_printf(¶m_indent, "%s ", indent);
|
string_printf(¶m_indent, "%s ", indent);
|
||||||
|
if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
|
||||||
|
_function_closure_string(str, fptr, param_indent.string TSRMLS_CC);
|
||||||
|
}
|
||||||
_function_parameter_string(str, fptr, param_indent.string TSRMLS_CC);
|
_function_parameter_string(str, fptr, param_indent.string TSRMLS_CC);
|
||||||
string_free(¶m_indent);
|
string_free(¶m_indent);
|
||||||
string_printf(str, "%s}\n", indent);
|
string_printf(str, "%s}\n", indent);
|
||||||
|
@ -1075,7 +1082,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_function_string(str, fptr, NULL, NULL, NULL, " " TSRMLS_CC);
|
_function_string(str, fptr, NULL, " " TSRMLS_CC);
|
||||||
func++;
|
func++;
|
||||||
}
|
}
|
||||||
string_printf(str, "%s }\n", indent);
|
string_printf(str, "%s }\n", indent);
|
||||||
|
@ -1164,12 +1171,15 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ reflection_parameter_factory */
|
/* {{{ reflection_parameter_factory */
|
||||||
static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC)
|
static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC)
|
||||||
{
|
{
|
||||||
reflection_object *intern;
|
reflection_object *intern;
|
||||||
parameter_reference *reference;
|
parameter_reference *reference;
|
||||||
zval *name;
|
zval *name;
|
||||||
|
|
||||||
|
if (closure_object) {
|
||||||
|
Z_ADDREF_P(closure_object);
|
||||||
|
}
|
||||||
MAKE_STD_ZVAL(name);
|
MAKE_STD_ZVAL(name);
|
||||||
if (arg_info->name) {
|
if (arg_info->name) {
|
||||||
ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
|
ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
|
||||||
|
@ -1186,16 +1196,20 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i
|
||||||
intern->ptr = reference;
|
intern->ptr = reference;
|
||||||
intern->ref_type = REF_TYPE_PARAMETER;
|
intern->ref_type = REF_TYPE_PARAMETER;
|
||||||
intern->ce = fptr->common.scope;
|
intern->ce = fptr->common.scope;
|
||||||
|
intern->obj = closure_object;
|
||||||
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ reflection_function_factory */
|
/* {{{ reflection_function_factory */
|
||||||
static void reflection_function_factory(zend_function *function, zval *object TSRMLS_DC)
|
static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object TSRMLS_DC)
|
||||||
{
|
{
|
||||||
reflection_object *intern;
|
reflection_object *intern;
|
||||||
zval *name;
|
zval *name;
|
||||||
|
|
||||||
|
if (closure_object) {
|
||||||
|
Z_ADDREF_P(closure_object);
|
||||||
|
}
|
||||||
MAKE_STD_ZVAL(name);
|
MAKE_STD_ZVAL(name);
|
||||||
ZVAL_STRING(name, function->common.function_name, 1);
|
ZVAL_STRING(name, function->common.function_name, 1);
|
||||||
|
|
||||||
|
@ -1204,17 +1218,21 @@ static void reflection_function_factory(zend_function *function, zval *object TS
|
||||||
intern->ptr = function;
|
intern->ptr = function;
|
||||||
intern->ref_type = REF_TYPE_FUNCTION;
|
intern->ref_type = REF_TYPE_FUNCTION;
|
||||||
intern->ce = NULL;
|
intern->ce = NULL;
|
||||||
|
intern->obj = closure_object;
|
||||||
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ reflection_method_factory */
|
/* {{{ reflection_method_factory */
|
||||||
static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *object TSRMLS_DC)
|
static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object TSRMLS_DC)
|
||||||
{
|
{
|
||||||
reflection_object *intern;
|
reflection_object *intern;
|
||||||
zval *name;
|
zval *name;
|
||||||
zval *classname;
|
zval *classname;
|
||||||
|
|
||||||
|
if (closure_object) {
|
||||||
|
Z_ADDREF_P(closure_object);
|
||||||
|
}
|
||||||
MAKE_STD_ZVAL(name);
|
MAKE_STD_ZVAL(name);
|
||||||
MAKE_STD_ZVAL(classname);
|
MAKE_STD_ZVAL(classname);
|
||||||
ZVAL_STRING(name, method->common.function_name, 1);
|
ZVAL_STRING(name, method->common.function_name, 1);
|
||||||
|
@ -1224,6 +1242,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
|
||||||
intern->ptr = method;
|
intern->ptr = method;
|
||||||
intern->ref_type = REF_TYPE_FUNCTION;
|
intern->ref_type = REF_TYPE_FUNCTION;
|
||||||
intern->ce = ce;
|
intern->ce = ce;
|
||||||
|
intern->obj = closure_object;
|
||||||
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
||||||
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
|
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
|
||||||
}
|
}
|
||||||
|
@ -1522,15 +1541,13 @@ ZEND_METHOD(reflection_function, __toString)
|
||||||
reflection_object *intern;
|
reflection_object *intern;
|
||||||
zend_function *fptr;
|
zend_function *fptr;
|
||||||
string str;
|
string str;
|
||||||
zval* name;
|
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) {
|
if (zend_parse_parameters_none() == FAILURE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GET_REFLECTION_OBJECT_PTR(fptr);
|
GET_REFLECTION_OBJECT_PTR(fptr);
|
||||||
_default_lookup_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
|
|
||||||
string_init(&str);
|
string_init(&str);
|
||||||
_function_string(&str, fptr, intern->ce, name, intern->obj, "" TSRMLS_CC);
|
_function_string(&str, fptr, intern->ce, "" TSRMLS_CC);
|
||||||
RETURN_STRINGL(str.string, str.len - 1, 0);
|
RETURN_STRINGL(str.string, str.len - 1, 0);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -1557,28 +1574,7 @@ ZEND_METHOD(reflection_function, isClosure)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GET_REFLECTION_OBJECT_PTR(fptr);
|
GET_REFLECTION_OBJECT_PTR(fptr);
|
||||||
RETURN_BOOL(intern->obj);
|
RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ proto public bool ReflectionFunction::getClosureThis()
|
|
||||||
Returns this pointer bound to closure */
|
|
||||||
ZEND_METHOD(reflection_function, getClosureThis)
|
|
||||||
{
|
|
||||||
reflection_object *intern;
|
|
||||||
zend_function *fptr;
|
|
||||||
zval* closure_this;
|
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GET_REFLECTION_OBJECT_PTR(fptr);
|
|
||||||
if (intern->obj) {
|
|
||||||
closure_this = zend_get_closure_this_ptr(intern->obj TSRMLS_CC);
|
|
||||||
if (closure_this) {
|
|
||||||
RETURN_ZVAL(closure_this, 1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -1719,22 +1715,6 @@ ZEND_METHOD(reflection_function, getStaticVariables)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ proto public mixed ReflectionFunction::getClosure()
|
|
||||||
Returns a dynamically created closure for the function */
|
|
||||||
ZEND_METHOD(reflection_function, getClosure)
|
|
||||||
{
|
|
||||||
reflection_object *intern;
|
|
||||||
zend_function *fptr;
|
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GET_REFLECTION_OBJECT_PTR(fptr);
|
|
||||||
|
|
||||||
zend_create_closure(return_value, fptr, NULL, NULL TSRMLS_CC);
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ proto public mixed ReflectionFunction::invoke(mixed* args)
|
/* {{{ proto public mixed ReflectionFunction::invoke(mixed* args)
|
||||||
Invokes the function */
|
Invokes the function */
|
||||||
ZEND_METHOD(reflection_function, invoke)
|
ZEND_METHOD(reflection_function, invoke)
|
||||||
|
@ -1912,7 +1892,7 @@ ZEND_METHOD(reflection_function, getParameters)
|
||||||
zval *parameter;
|
zval *parameter;
|
||||||
|
|
||||||
ALLOC_ZVAL(parameter);
|
ALLOC_ZVAL(parameter);
|
||||||
reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
|
reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), intern->obj, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
|
||||||
add_next_index_zval(return_value, parameter);
|
add_next_index_zval(return_value, parameter);
|
||||||
|
|
||||||
arg_info++;
|
arg_info++;
|
||||||
|
@ -1989,6 +1969,7 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||||
struct _zend_arg_info *arg_info;
|
struct _zend_arg_info *arg_info;
|
||||||
int position;
|
int position;
|
||||||
zend_class_entry *ce = NULL;
|
zend_class_entry *ce = NULL;
|
||||||
|
zend_bool is_closure = 0;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zZ", &reference, ¶meter) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zZ", &reference, ¶meter) == FAILURE) {
|
||||||
return;
|
return;
|
||||||
|
@ -2053,7 +2034,8 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||||
&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
|
&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
|
||||||
&& (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
|
&& (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
|
||||||
{
|
{
|
||||||
/* nothign to do */
|
/* nothign to do. don't set is_closure since is the invoke handler,
|
||||||
|
not the closure itself */
|
||||||
} else if (zend_hash_find(&ce->function_table, lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
|
} else if (zend_hash_find(&ce->function_table, lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
|
||||||
efree(lcname);
|
efree(lcname);
|
||||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||||
|
@ -2068,7 +2050,9 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||||
ce = Z_OBJCE_P(reference);
|
ce = Z_OBJCE_P(reference);
|
||||||
|
|
||||||
if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
|
if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
|
||||||
fptr = zend_get_closure_invoke_method(reference TSRMLS_CC);
|
fptr = (zend_function *)zend_get_closure_method_def(reference TSRMLS_CC);
|
||||||
|
Z_ADDREF_P(reference);
|
||||||
|
is_closure = 1;
|
||||||
} else if (zend_hash_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME), (void **)&fptr) == FAILURE) {
|
} else if (zend_hash_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME), (void **)&fptr) == FAILURE) {
|
||||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||||
"Method %s::%s() does not exist", ce->name, ZEND_INVOKE_FUNC_NAME);
|
"Method %s::%s() does not exist", ce->name, ZEND_INVOKE_FUNC_NAME);
|
||||||
|
@ -2132,10 +2116,13 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||||
ref->offset = (zend_uint)position;
|
ref->offset = (zend_uint)position;
|
||||||
ref->required = fptr->common.required_num_args;
|
ref->required = fptr->common.required_num_args;
|
||||||
ref->fptr = fptr;
|
ref->fptr = fptr;
|
||||||
// TODO: copy fptr
|
/* TODO: copy fptr */
|
||||||
intern->ptr = ref;
|
intern->ptr = ref;
|
||||||
intern->ref_type = REF_TYPE_PARAMETER;
|
intern->ref_type = REF_TYPE_PARAMETER;
|
||||||
intern->ce = ce;
|
intern->ce = ce;
|
||||||
|
if (reference && is_closure) {
|
||||||
|
intern->obj = reference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -2181,9 +2168,9 @@ ZEND_METHOD(reflection_parameter, getDeclaringFunction)
|
||||||
GET_REFLECTION_OBJECT_PTR(param);
|
GET_REFLECTION_OBJECT_PTR(param);
|
||||||
|
|
||||||
if (!param->fptr->common.scope) {
|
if (!param->fptr->common.scope) {
|
||||||
reflection_function_factory(_copy_function(param->fptr TSRMLS_CC), return_value TSRMLS_CC);
|
reflection_function_factory(_copy_function(param->fptr TSRMLS_CC), intern->obj, return_value TSRMLS_CC);
|
||||||
} else {
|
} else {
|
||||||
reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr TSRMLS_CC), return_value TSRMLS_CC);
|
reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr TSRMLS_CC), intern->obj, return_value TSRMLS_CC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -2431,11 +2418,7 @@ ZEND_METHOD(reflection_method, __construct)
|
||||||
int name_len, tmp_len;
|
int name_len, tmp_len;
|
||||||
zval ztmp;
|
zval ztmp;
|
||||||
|
|
||||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o", &classname) == SUCCESS) {
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
|
||||||
name_str = ZEND_INVOKE_FUNC_NAME;
|
|
||||||
name_len = sizeof(ZEND_INVOKE_FUNC_NAME)-1;
|
|
||||||
orig_obj = classname;
|
|
||||||
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2504,45 +2487,15 @@ ZEND_METHOD(reflection_method, __construct)
|
||||||
{
|
{
|
||||||
/* do nothing, mptr already set */
|
/* do nothing, mptr already set */
|
||||||
} else if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
|
} else if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
|
||||||
/* Check if this is a property storing a closure */
|
efree(lcname);
|
||||||
mptr = NULL; /* Set by closure detection again */
|
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||||
if (orig_obj) {
|
"Method %s::%s() does not exist", ce->name, name_str);
|
||||||
zval **callable, member;
|
return;
|
||||||
zend_property_info *property_info;
|
|
||||||
zend_object *zobj = zend_objects_get_address(orig_obj TSRMLS_CC);
|
|
||||||
|
|
||||||
ZVAL_STRINGL(&member, name_str, name_len, 0);
|
|
||||||
property_info = zend_get_property_info(ce, &member, 1 TSRMLS_CC);
|
|
||||||
|
|
||||||
if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &callable) == SUCCESS) {
|
|
||||||
zval *callable_obj;
|
|
||||||
zend_class_entry *ce_ptr;
|
|
||||||
zend_function *fbc;
|
|
||||||
|
|
||||||
if (Z_TYPE_PP(callable) == IS_OBJECT
|
|
||||||
&& Z_OBJ_HANDLER_PP(callable, get_closure)
|
|
||||||
&& Z_OBJ_HANDLER_PP(callable, get_closure)(*callable, &ce_ptr, &fbc, &callable_obj TSRMLS_CC) == SUCCESS) {
|
|
||||||
mptr = fbc;
|
|
||||||
Z_ADDREF_PP(callable);
|
|
||||||
intern->obj = *callable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!mptr) {
|
|
||||||
efree(lcname);
|
|
||||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
|
||||||
"Method %s::%s() does not exist", ce->name, name_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
efree(lcname);
|
efree(lcname);
|
||||||
|
|
||||||
MAKE_STD_ZVAL(name);
|
MAKE_STD_ZVAL(name);
|
||||||
if (intern->obj) {
|
ZVAL_STRING(name, mptr->common.function_name, 1);
|
||||||
ZVAL_STRINGL(name, name_str, name_len, 1);
|
|
||||||
} else {
|
|
||||||
ZVAL_STRING(name, mptr->common.function_name, 1);
|
|
||||||
}
|
|
||||||
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
||||||
intern->ptr = mptr;
|
intern->ptr = mptr;
|
||||||
intern->ref_type = REF_TYPE_FUNCTION;
|
intern->ref_type = REF_TYPE_FUNCTION;
|
||||||
|
@ -2557,54 +2510,17 @@ ZEND_METHOD(reflection_method, __toString)
|
||||||
reflection_object *intern;
|
reflection_object *intern;
|
||||||
zend_function *mptr;
|
zend_function *mptr;
|
||||||
string str;
|
string str;
|
||||||
zval *name;
|
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) {
|
if (zend_parse_parameters_none() == FAILURE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GET_REFLECTION_OBJECT_PTR(mptr);
|
GET_REFLECTION_OBJECT_PTR(mptr);
|
||||||
_default_lookup_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
|
|
||||||
string_init(&str);
|
string_init(&str);
|
||||||
_function_string(&str, mptr, intern->ce, name, intern->obj, "" TSRMLS_CC);
|
_function_string(&str, mptr, intern->ce, "" TSRMLS_CC);
|
||||||
RETURN_STRINGL(str.string, str.len - 1, 0);
|
RETURN_STRINGL(str.string, str.len - 1, 0);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
|
|
||||||
Invokes the function */
|
|
||||||
ZEND_METHOD(reflection_method, getClosure)
|
|
||||||
{
|
|
||||||
reflection_object *intern;
|
|
||||||
zval *obj;
|
|
||||||
zend_function *mptr;
|
|
||||||
|
|
||||||
METHOD_NOTSTATIC(reflection_method_ptr);
|
|
||||||
GET_REFLECTION_OBJECT_PTR(mptr);
|
|
||||||
|
|
||||||
if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
|
|
||||||
zend_create_closure(return_value, mptr, mptr->common.scope, NULL TSRMLS_CC);
|
|
||||||
} else {
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope TSRMLS_CC)) {
|
|
||||||
_DO_THROW("Given object is not an instance of the class this method was declared in");
|
|
||||||
/* Returns from this function */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is an original closure object and __invoke is to be called. */
|
|
||||||
if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION &&
|
|
||||||
(mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
|
|
||||||
{
|
|
||||||
RETURN_ZVAL(obj, 1, 0);
|
|
||||||
} else {
|
|
||||||
zend_create_closure(return_value, mptr, mptr->common.scope, obj TSRMLS_CC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
|
/* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
|
||||||
Invokes the method. */
|
Invokes the method. */
|
||||||
ZEND_METHOD(reflection_method, invoke)
|
ZEND_METHOD(reflection_method, invoke)
|
||||||
|
@ -3017,7 +2933,7 @@ ZEND_METHOD(reflection_method, getPrototype)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, return_value TSRMLS_CC);
|
reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value TSRMLS_CC);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -3397,7 +3313,7 @@ ZEND_METHOD(reflection_class, getConstructor)
|
||||||
GET_REFLECTION_OBJECT_PTR(ce);
|
GET_REFLECTION_OBJECT_PTR(ce);
|
||||||
|
|
||||||
if (ce->constructor) {
|
if (ce->constructor) {
|
||||||
reflection_method_factory(ce, ce->constructor, return_value TSRMLS_CC);
|
reflection_method_factory(ce, ce->constructor, NULL, return_value TSRMLS_CC);
|
||||||
} else {
|
} else {
|
||||||
RETURN_NULL();
|
RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
@ -3451,10 +3367,12 @@ ZEND_METHOD(reflection_class, getMethod)
|
||||||
&& memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
|
&& memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
|
||||||
&& (mptr = zend_get_closure_invoke_method(intern->obj TSRMLS_CC)) != NULL)
|
&& (mptr = zend_get_closure_invoke_method(intern->obj TSRMLS_CC)) != NULL)
|
||||||
{
|
{
|
||||||
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
|
/* don't assign closure_object since we only reflect the invoke handler
|
||||||
|
method and not the closure definition itself */
|
||||||
|
reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
|
||||||
efree(lc_name);
|
efree(lc_name);
|
||||||
} else if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
|
} else if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
|
||||||
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
|
reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
|
||||||
efree(lc_name);
|
efree(lc_name);
|
||||||
} else {
|
} else {
|
||||||
efree(lc_name);
|
efree(lc_name);
|
||||||
|
@ -3480,7 +3398,10 @@ static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval,
|
||||||
{
|
{
|
||||||
mptr = closure;
|
mptr = closure;
|
||||||
}
|
}
|
||||||
reflection_method_factory(ce, mptr, method TSRMLS_CC);
|
/* don't assign closure_object since we only reflect the invoke handler
|
||||||
|
method and not the closure definition itself, even if we have a
|
||||||
|
closure */
|
||||||
|
reflection_method_factory(ce, mptr, NULL, method TSRMLS_CC);
|
||||||
add_next_index_zval(retval, method);
|
add_next_index_zval(retval, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4839,7 +4760,7 @@ ZEND_METHOD(reflection_extension, getFunctions)
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOC_ZVAL(function);
|
ALLOC_ZVAL(function);
|
||||||
reflection_function_factory(fptr, function TSRMLS_CC);
|
reflection_function_factory(fptr, NULL, function TSRMLS_CC);
|
||||||
add_assoc_zval_ex(return_value, func->fname, strlen(func->fname)+1, function);
|
add_assoc_zval_ex(return_value, func->fname, strlen(func->fname)+1, function);
|
||||||
func++;
|
func++;
|
||||||
}
|
}
|
||||||
|
@ -5090,7 +5011,6 @@ static const zend_function_entry reflection_function_abstract_functions[] = {
|
||||||
ZEND_ME(reflection_function, isDeprecated, NULL, 0)
|
ZEND_ME(reflection_function, isDeprecated, NULL, 0)
|
||||||
ZEND_ME(reflection_function, isInternal, NULL, 0)
|
ZEND_ME(reflection_function, isInternal, NULL, 0)
|
||||||
ZEND_ME(reflection_function, isUserDefined, NULL, 0)
|
ZEND_ME(reflection_function, isUserDefined, NULL, 0)
|
||||||
ZEND_ME(reflection_function, getClosureThis, NULL, 0)
|
|
||||||
ZEND_ME(reflection_function, getDocComment, NULL, 0)
|
ZEND_ME(reflection_function, getDocComment, NULL, 0)
|
||||||
ZEND_ME(reflection_function, getEndLine, NULL, 0)
|
ZEND_ME(reflection_function, getEndLine, NULL, 0)
|
||||||
ZEND_ME(reflection_function, getExtension, NULL, 0)
|
ZEND_ME(reflection_function, getExtension, NULL, 0)
|
||||||
|
@ -5113,7 +5033,6 @@ static const zend_function_entry reflection_function_functions[] = {
|
||||||
ZEND_ME(reflection_function, __toString, NULL, 0)
|
ZEND_ME(reflection_function, __toString, NULL, 0)
|
||||||
ZEND_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
|
ZEND_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(reflection_function, isDisabled, NULL, 0)
|
ZEND_ME(reflection_function, isDisabled, NULL, 0)
|
||||||
ZEND_ME(reflection_function, getClosure, NULL, 0)
|
|
||||||
ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
|
ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
|
||||||
ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
|
ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
|
@ -5153,7 +5072,6 @@ static const zend_function_entry reflection_method_functions[] = {
|
||||||
ZEND_ME(reflection_method, isConstructor, NULL, 0)
|
ZEND_ME(reflection_method, isConstructor, NULL, 0)
|
||||||
ZEND_ME(reflection_method, isDestructor, NULL, 0)
|
ZEND_ME(reflection_method, isDestructor, NULL, 0)
|
||||||
ZEND_ME(reflection_method, getModifiers, NULL, 0)
|
ZEND_ME(reflection_method, getModifiers, NULL, 0)
|
||||||
ZEND_ME(reflection_method, getClosure, NULL, 0)
|
|
||||||
ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
|
ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
|
||||||
ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
|
ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
|
||||||
ZEND_ME(reflection_method, getDeclaringClass, NULL, 0)
|
ZEND_ME(reflection_method, getDeclaringClass, NULL, 0)
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
--TEST--
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$global = 42;
|
|
||||||
|
|
||||||
$func = function($x, stdClass $y=NULL) use($global) {
|
|
||||||
static $static;
|
|
||||||
};
|
|
||||||
|
|
||||||
ReflectionFunction::Export($func);
|
|
||||||
|
|
||||||
$r = new ReflectionFunction($func);
|
|
||||||
|
|
||||||
var_dump(@get_class($r->getClosureThis()));
|
|
||||||
var_dump($r->getName());
|
|
||||||
var_dump($r->isClosure());
|
|
||||||
|
|
||||||
Class Test {
|
|
||||||
public $func;
|
|
||||||
function __construct(){
|
|
||||||
global $global;
|
|
||||||
$this->func = function($x, stdClass $y = NULL) use($global) {
|
|
||||||
static $static;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReflectionMethod::export(new Test, "func");
|
|
||||||
|
|
||||||
$r = new ReflectionMethod(new Test, "func");
|
|
||||||
|
|
||||||
var_dump(get_class($r->getClosureThis()));
|
|
||||||
var_dump($r->getName());
|
|
||||||
var_dump($r->isClosure());
|
|
||||||
|
|
||||||
?>
|
|
||||||
===DONE===
|
|
||||||
--EXPECTF--
|
|
||||||
Closure [ <user> function {closure} ] {
|
|
||||||
@@ %s027.php 5 - 7
|
|
||||||
|
|
||||||
- Static Parameters [2] {
|
|
||||||
Parameter #0 [ $global ]
|
|
||||||
Parameter #1 [ $static ]
|
|
||||||
}
|
|
||||||
|
|
||||||
- Parameters [2] {
|
|
||||||
Parameter #0 [ <required> $x ]
|
|
||||||
Parameter #1 [ <optional> stdClass or NULL $y = NULL ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NULL
|
|
||||||
string(9) "{closure}"
|
|
||||||
bool(true)
|
|
||||||
Closure [ <user> public method func ] {
|
|
||||||
@@ %s027.php 21 - 23
|
|
||||||
|
|
||||||
- Static Parameters [3] {
|
|
||||||
Parameter #0 [ Test $this ]
|
|
||||||
Parameter #1 [ $global ]
|
|
||||||
Parameter #2 [ $static ]
|
|
||||||
}
|
|
||||||
|
|
||||||
- Parameters [2] {
|
|
||||||
Parameter #0 [ <required> $x ]
|
|
||||||
Parameter #1 [ <optional> stdClass or NULL $y = NULL ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string(4) "Test"
|
|
||||||
string(4) "func"
|
|
||||||
bool(true)
|
|
||||||
===DONE===
|
|
|
@ -1,37 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Test ReflectionFunction::getClosure() function : basic functionality
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
/* Prototype : public mixed ReflectionFunction::getClosure()
|
|
||||||
* Description: Returns a dynamically created closure for the function
|
|
||||||
* Source code: ext/reflection/php_reflection.c
|
|
||||||
* Alias to functions:
|
|
||||||
*/
|
|
||||||
|
|
||||||
echo "*** Testing ReflectionFunction::getClosure() : basic functionality ***\n";
|
|
||||||
|
|
||||||
function foo()
|
|
||||||
{
|
|
||||||
var_dump( "Inside foo function" );
|
|
||||||
}
|
|
||||||
|
|
||||||
function bar( $arg )
|
|
||||||
{
|
|
||||||
var_dump( "Arg is " . $arg );
|
|
||||||
}
|
|
||||||
|
|
||||||
$func = new ReflectionFunction( 'foo' );
|
|
||||||
$closure = $func->getClosure();
|
|
||||||
$closure();
|
|
||||||
|
|
||||||
$func = new ReflectionFunction( 'bar' );
|
|
||||||
$closure = $func->getClosure();
|
|
||||||
$closure( 'succeeded' );
|
|
||||||
|
|
||||||
?>
|
|
||||||
===DONE===
|
|
||||||
--EXPECTF--
|
|
||||||
*** Testing ReflectionFunction::getClosure() : basic functionality ***
|
|
||||||
%unicode|string%(19) "Inside foo function"
|
|
||||||
%unicode|string%(16) "Arg is succeeded"
|
|
||||||
===DONE===
|
|
|
@ -1,27 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Test ReflectionFunction::getClosure() function : error functionality
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
/* Prototype : public mixed ReflectionFunction::getClosure()
|
|
||||||
* Description: Returns a dynamically created closure for the function
|
|
||||||
* Source code: ext/reflection/php_reflection.c
|
|
||||||
* Alias to functions:
|
|
||||||
*/
|
|
||||||
|
|
||||||
echo "*** Testing ReflectionFunction::getClosure() : error conditions ***\n";
|
|
||||||
|
|
||||||
function foo()
|
|
||||||
{
|
|
||||||
var_dump( "Inside foo function" );
|
|
||||||
}
|
|
||||||
|
|
||||||
$func = new ReflectionFunction( 'foo' );
|
|
||||||
$closure = $func->getClosure('bar');
|
|
||||||
|
|
||||||
?>
|
|
||||||
===DONE===
|
|
||||||
--EXPECTF--
|
|
||||||
*** Testing ReflectionFunction::getClosure() : error conditions ***
|
|
||||||
|
|
||||||
Warning: ReflectionFunction::getClosure() expects exactly 0 parameters, 1 given in %s on line %d
|
|
||||||
===DONE===
|
|
|
@ -1,55 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Test ReflectionMethod::getClosure() function : basic functionality
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
/* Prototype : public mixed ReflectionFunction::getClosure()
|
|
||||||
* Description: Returns a dynamically created closure for the method
|
|
||||||
* Source code: ext/reflection/php_reflection.c
|
|
||||||
* Alias to functions:
|
|
||||||
*/
|
|
||||||
|
|
||||||
echo "*** Testing ReflectionMethod::getClosure() : basic functionality ***\n";
|
|
||||||
|
|
||||||
class StaticExample
|
|
||||||
{
|
|
||||||
static function foo()
|
|
||||||
{
|
|
||||||
var_dump( "Static Example class, Hello World!" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Example
|
|
||||||
{
|
|
||||||
public $bar = 42;
|
|
||||||
public function foo()
|
|
||||||
{
|
|
||||||
var_dump( "Example class, bar: " . $this->bar );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize classes
|
|
||||||
$class = new ReflectionClass( 'Example' );
|
|
||||||
$staticclass = new ReflectionClass( 'StaticExample' );
|
|
||||||
$object = new Example();
|
|
||||||
$fakeobj = new StdClass();
|
|
||||||
|
|
||||||
|
|
||||||
$method = $staticclass->getMethod( 'foo' );
|
|
||||||
$closure = $method->getClosure();
|
|
||||||
$closure();
|
|
||||||
|
|
||||||
$method = $class->getMethod( 'foo' );
|
|
||||||
|
|
||||||
$closure = $method->getClosure( $object );
|
|
||||||
$closure();
|
|
||||||
$object->bar = 34;
|
|
||||||
$closure();
|
|
||||||
|
|
||||||
?>
|
|
||||||
===DONE===
|
|
||||||
--EXPECTF--
|
|
||||||
*** Testing ReflectionMethod::getClosure() : basic functionality ***
|
|
||||||
%unicode|string%(34) "Static Example class, Hello World!"
|
|
||||||
%unicode|string%(22) "Example class, bar: 42"
|
|
||||||
%unicode|string%(22) "Example class, bar: 34"
|
|
||||||
===DONE===
|
|
|
@ -1,77 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Test ReflectionMethod::getClosure() function : error functionality
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
/* Prototype : public mixed ReflectionFunction::getClosure()
|
|
||||||
* Description: Returns a dynamically created closure for the method
|
|
||||||
* Source code: ext/reflection/php_reflection.c
|
|
||||||
* Alias to functions:
|
|
||||||
*/
|
|
||||||
|
|
||||||
echo "*** Testing ReflectionMethod::getClosure() : error conditions ***\n";
|
|
||||||
|
|
||||||
class StaticExample
|
|
||||||
{
|
|
||||||
static function foo()
|
|
||||||
{
|
|
||||||
var_dump( "Static Example class, Hello World!" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Example
|
|
||||||
{
|
|
||||||
public $bar = 42;
|
|
||||||
public function foo()
|
|
||||||
{
|
|
||||||
var_dump( "Example class, bar: " . $this->bar );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize classes
|
|
||||||
$class = new ReflectionClass( 'Example' );
|
|
||||||
$staticclass = new ReflectionClass( 'StaticExample' );
|
|
||||||
$method = $class->getMethod( 'foo' );
|
|
||||||
$staticmethod = $staticclass->getMethod( 'foo' );
|
|
||||||
$object = new Example();
|
|
||||||
$fakeobj = new StdClass();
|
|
||||||
|
|
||||||
echo "\n-- Testing ReflectionMethod::getClosure() function with more than expected no. of arguments --\n";
|
|
||||||
var_dump( $staticmethod->getClosure( 'foobar' ) );
|
|
||||||
var_dump( $staticmethod->getClosure( 'foo', 'bar' ) );
|
|
||||||
var_dump( $method->getClosure( $object, 'foobar' ) );
|
|
||||||
|
|
||||||
echo "\n-- Testing ReflectionMethod::getClosure() function with Zero arguments --\n";
|
|
||||||
$closure = $method->getClosure();
|
|
||||||
|
|
||||||
echo "\n-- Testing ReflectionMethod::getClosure() function with Zero arguments --\n";
|
|
||||||
try {
|
|
||||||
var_dump( $method->getClosure( $fakeobj ) );
|
|
||||||
} catch( Exception $e ) {
|
|
||||||
var_dump( $e->getMessage() );
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
===DONE===
|
|
||||||
--EXPECTF--
|
|
||||||
*** Testing ReflectionMethod::getClosure() : error conditions ***
|
|
||||||
|
|
||||||
-- Testing ReflectionMethod::getClosure() function with more than expected no. of arguments --
|
|
||||||
object(Closure)#%d (1) {
|
|
||||||
["this"]=>
|
|
||||||
NULL
|
|
||||||
}
|
|
||||||
object(Closure)#%d (1) {
|
|
||||||
["this"]=>
|
|
||||||
NULL
|
|
||||||
}
|
|
||||||
|
|
||||||
Warning: ReflectionMethod::getClosure() expects exactly 1 parameter, 2 given in %s on line %d
|
|
||||||
NULL
|
|
||||||
|
|
||||||
-- Testing ReflectionMethod::getClosure() function with Zero arguments --
|
|
||||||
|
|
||||||
Warning: ReflectionMethod::getClosure() expects exactly 1 parameter, 0 given in %s on line %d
|
|
||||||
|
|
||||||
-- Testing ReflectionMethod::getClosure() function with Zero arguments --
|
|
||||||
%unicode|string%(72) "Given object is not an instance of the class this method was declared in"
|
|
||||||
===DONE===
|
|
|
@ -19,7 +19,7 @@ foreach($rms as $rm) {
|
||||||
|
|
||||||
echo "---\n";
|
echo "---\n";
|
||||||
|
|
||||||
$rm = new ReflectionMethod($closure);
|
$rm = new ReflectionMethod($closure, '__invoke');
|
||||||
var_dump($rm->getName());
|
var_dump($rm->getName());
|
||||||
var_dump($rm->getNumberOfParameters());
|
var_dump($rm->getNumberOfParameters());
|
||||||
var_dump($rm->getNumberOfRequiredParameters());
|
var_dump($rm->getNumberOfRequiredParameters());
|
||||||
|
|
|
@ -7,15 +7,15 @@ class Test {
|
||||||
function __invoke($a, $b = 0) { }
|
function __invoke($a, $b = 0) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
$rm = new ReflectionMethod(new Test);
|
$rm = new ReflectionMethod(new Test, '__invoke');
|
||||||
var_dump($rm->getName());
|
var_dump($rm->getName());
|
||||||
var_dump($rm->getNumberOfParameters());
|
var_dump($rm->getNumberOfParameters());
|
||||||
var_dump($rm->getNumberOfRequiredParameters());
|
var_dump($rm->getNumberOfRequiredParameters());
|
||||||
|
|
||||||
$rp = new ReflectionParameter(new Test, 0);
|
$rp = new ReflectionParameter(array(new Test, '__invoke'), 0);
|
||||||
var_dump($rp->isOptional());
|
var_dump($rp->isOptional());
|
||||||
|
|
||||||
$rp = new ReflectionParameter(new Test, 1);
|
$rp = new ReflectionParameter(array(new Test, '__invoke'), 1);
|
||||||
var_dump($rp->isOptional());
|
var_dump($rp->isOptional());
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -5,14 +5,14 @@ Reflection on closures: Segfaults with getParameters() and getDeclaringFunction(
|
||||||
|
|
||||||
$closure = function($a, $b = 0) { };
|
$closure = function($a, $b = 0) { };
|
||||||
|
|
||||||
$method = new ReflectionMethod ($closure);
|
$method = new ReflectionMethod ($closure, '__invoke');
|
||||||
$params = $method->getParameters ();
|
$params = $method->getParameters ();
|
||||||
unset ($method);
|
unset ($method);
|
||||||
$method = $params[0]->getDeclaringFunction ();
|
$method = $params[0]->getDeclaringFunction ();
|
||||||
unset ($params);
|
unset ($params);
|
||||||
echo $method->getName ()."\n";
|
echo $method->getName ()."\n";
|
||||||
|
|
||||||
$parameter = new ReflectionParameter ($closure, 'b');
|
$parameter = new ReflectionParameter (array ($closure, '__invoke'), 'b');
|
||||||
$method = $parameter->getDeclaringFunction ();
|
$method = $parameter->getDeclaringFunction ();
|
||||||
unset ($parameter);
|
unset ($parameter);
|
||||||
echo $method->getName ()."\n";
|
echo $method->getName ()."\n";
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
--TEST--
|
|
||||||
Reflection on closures: Segfault with getClosure() on closure itself
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$closure = function() { echo "Invoked!\n"; };
|
|
||||||
|
|
||||||
$method = new ReflectionMethod ($closure);
|
|
||||||
|
|
||||||
$closure2 = $method->getClosure ($closure);
|
|
||||||
|
|
||||||
$closure2 ();
|
|
||||||
$closure2->__invoke ();
|
|
||||||
|
|
||||||
unset ($closure);
|
|
||||||
|
|
||||||
$closure2 ();
|
|
||||||
$closure2->__invoke ();
|
|
||||||
|
|
||||||
?>
|
|
||||||
===DONE===
|
|
||||||
--EXPECTF--
|
|
||||||
Invoked!
|
|
||||||
Invoked!
|
|
||||||
Invoked!
|
|
||||||
Invoked!
|
|
||||||
===DONE===
|
|
Loading…
Add table
Add a link
Reference in a new issue