@@ -1438,20 +1438,41 @@ static void reflection_type_factory(
1438
1438
}
1439
1439
}
1440
1440
1441
- /* {{{ reflection_function_factory */
1442
- static void reflection_function_factory (zend_function * function , zval * closure_object , zval * object )
1441
+ /* copy of hidden zend_closure */
1442
+ typedef struct _zend_closure {
1443
+ zend_object std ;
1444
+ zend_function func ;
1445
+ zval this_ptr ;
1446
+ zend_class_entry * called_scope ;
1447
+ zif_handler orig_internal_handler ;
1448
+ } zend_closure ;
1449
+
1450
+ static void reflection_function_create_common (zend_function * function , zend_object * closure_object , zval * object )
1443
1451
{
1444
- reflection_object * intern ;
1445
- reflection_instantiate (reflection_function_ptr , object );
1446
- intern = Z_REFLECTION_P (object );
1452
+ reflection_object * intern = Z_REFLECTION_P (object );
1453
+
1447
1454
intern -> ptr = function ;
1448
1455
intern -> ref_type = REF_TYPE_FUNCTION ;
1449
1456
intern -> ce = NULL ;
1450
1457
if (closure_object ) {
1451
- ZVAL_OBJ_COPY (& intern -> obj , Z_OBJ_P (closure_object ));
1458
+ ZVAL_OBJ_COPY (& intern -> obj , closure_object );
1459
+ zend_closure * closure = (zend_closure * ) closure_object ;
1460
+ /* if it is bound to a class, resolve to it */
1461
+ if (closure -> called_scope ) {
1462
+ intern -> ce = closure -> called_scope ;
1463
+ }
1464
+ } else {
1465
+ ZVAL_UNDEF (& intern -> obj );
1452
1466
}
1453
1467
ZVAL_STR_COPY (reflection_prop_name (object ), function -> common .function_name );
1454
1468
}
1469
+
1470
+ /* {{{ reflection_function_factory */
1471
+ static void reflection_function_factory (zend_function * function , zend_object * closure_object , zval * object )
1472
+ {
1473
+ reflection_instantiate (reflection_function_ptr , object );
1474
+ reflection_function_create_common (function , closure_object , object );
1475
+ }
1455
1476
/* }}} */
1456
1477
1457
1478
/* {{{ reflection_method_factory */
@@ -1603,27 +1624,18 @@ ZEND_METHOD(Reflection, getModifierNames)
1603
1624
/* {{{ Constructor. Throws an Exception in case the given function does not exist */
1604
1625
ZEND_METHOD (ReflectionFunction , __construct )
1605
1626
{
1606
- zval * object ;
1607
1627
zend_object * closure_obj = NULL ;
1608
- reflection_object * intern ;
1628
+ zend_string * fname = NULL ;
1609
1629
zend_function * fptr ;
1610
- zend_string * fname , * lcname ;
1611
-
1612
- object = ZEND_THIS ;
1613
- intern = Z_REFLECTION_P (object );
1614
1630
1615
1631
ZEND_PARSE_PARAMETERS_START (1 , 1 )
1616
1632
Z_PARAM_OBJ_OF_CLASS_OR_STR (closure_obj , zend_ce_closure , fname )
1617
1633
ZEND_PARSE_PARAMETERS_END ();
1618
1634
1619
- /* Set CE to NULL */
1620
- intern -> ce = NULL ;
1621
1635
if (closure_obj ) {
1622
1636
fptr = (zend_function * )zend_get_closure_method_def (closure_obj );
1623
- //zend_object *tmp = NULL;
1624
- ///* We use the get_closure object handler that always succeds to fetch the function and CE pointers */
1625
- //closure_obj->handlers->get_closure(closure_obj, &intern->ce, &fptr, /* obj_ptr */ &tmp, /* check_only */ false);
1626
1637
} else {
1638
+ zend_string * lcname ;
1627
1639
if (UNEXPECTED (ZSTR_VAL (fname )[0 ] == '\\' )) {
1628
1640
/* Ignore leading "\" */
1629
1641
ALLOCA_FLAG (use_heap )
@@ -1644,19 +1656,15 @@ ZEND_METHOD(ReflectionFunction, __construct)
1644
1656
}
1645
1657
}
1646
1658
1647
- if (intern -> ptr ) {
1648
- zval_ptr_dtor (& intern -> obj );
1649
- zval_ptr_dtor (reflection_prop_name (object ));
1650
- }
1659
+ // TODO How can this ever be hit?
1660
+ //zval *object = ZEND_THIS;
1661
+ //reflection_object *intern = Z_REFLECTION_P(object);
1662
+ //if (intern->ptr) {
1663
+ // zval_ptr_dtor(&intern->obj);
1664
+ // zval_ptr_dtor(reflection_prop_name(object));
1665
+ //}
1651
1666
1652
- ZVAL_STR_COPY (reflection_prop_name (object ), fptr -> common .function_name );
1653
- intern -> ptr = fptr ;
1654
- intern -> ref_type = REF_TYPE_FUNCTION ;
1655
- if (closure_obj ) {
1656
- ZVAL_OBJ_COPY (& intern -> obj , closure_obj );
1657
- } else {
1658
- ZVAL_UNDEF (& intern -> obj );
1659
- }
1667
+ reflection_function_create_common (fptr , closure_obj , ZEND_THIS );
1660
1668
}
1661
1669
/* }}} */
1662
1670
@@ -2360,9 +2368,7 @@ ZEND_METHOD(ReflectionGenerator, getFunction)
2360
2368
REFLECTION_CHECK_VALID_GENERATOR (ex )
2361
2369
2362
2370
if (ex -> func -> common .fn_flags & ZEND_ACC_CLOSURE ) {
2363
- zval closure ;
2364
- ZVAL_OBJ (& closure , ZEND_CLOSURE_OBJECT (ex -> func ));
2365
- reflection_function_factory (ex -> func , & closure , return_value );
2371
+ reflection_function_factory (ex -> func , ZEND_CLOSURE_OBJECT (ex -> func ), return_value );
2366
2372
} else if (ex -> func -> op_array .scope ) {
2367
2373
reflection_method_factory (ex -> func -> op_array .scope , ex -> func , NULL , return_value );
2368
2374
} else {
@@ -2645,7 +2651,7 @@ ZEND_METHOD(ReflectionParameter, getDeclaringFunction)
2645
2651
GET_REFLECTION_OBJECT_PTR (param );
2646
2652
2647
2653
if (!param -> fptr -> common .scope ) {
2648
- reflection_function_factory (_copy_function (param -> fptr ), Z_ISUNDEF (intern -> obj )? NULL : & intern -> obj , return_value );
2654
+ reflection_function_factory (_copy_function (param -> fptr ), Z_ISUNDEF (intern -> obj )? NULL : Z_OBJ ( intern -> obj ) , return_value );
2649
2655
} else {
2650
2656
reflection_method_factory (param -> fptr -> common .scope , _copy_function (param -> fptr ), Z_ISUNDEF (intern -> obj )? NULL : & intern -> obj , return_value );
2651
2657
}
@@ -3130,7 +3136,7 @@ ZEND_METHOD(ReflectionNamedType, isBuiltin)
3130
3136
}
3131
3137
/* }}} */
3132
3138
3133
- /* {{{ Returns whether type is a builtin type */
3139
+ /* {{{ Resolve a relative class type to a proper named type */
3134
3140
ZEND_METHOD (ReflectionRelativeClassType , resolveToNamedType )
3135
3141
{
3136
3142
reflection_object * intern ;
@@ -3166,9 +3172,19 @@ ZEND_METHOD(ReflectionRelativeClassType, resolveToNamedType)
3166
3172
}
3167
3173
resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (intern -> ce -> name , allows_null , /* extra flags */ 0 );
3168
3174
} else {
3169
- ZEND_ASSERT (zend_string_equals_literal_ci (ZEND_TYPE_NAME (param -> type ), "self" ) || zend_string_equals_literal_ci (ZEND_TYPE_NAME (param -> type ), "parent" ));
3170
3175
ZEND_ASSERT (ZEND_TYPE_HAS_NAME (param -> type ));
3171
- resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (ZEND_TYPE_NAME (param -> type ), allows_null , /* extra flags */ 0 );
3176
+ ZEND_ASSERT (zend_string_equals_literal_ci (ZEND_TYPE_NAME (param -> type ), "self" ) || zend_string_equals_literal_ci (ZEND_TYPE_NAME (param -> type ), "parent" ));
3177
+
3178
+ if (zend_string_equals_literal_ci (ZEND_TYPE_NAME (param -> type ), "self" )) {
3179
+ resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (intern -> ce -> name , allows_null , /* extra flags */ 0 );
3180
+ } else {
3181
+ if (!intern -> ce -> parent ) {
3182
+ zend_throw_exception_ex (reflection_exception_ptr , 0 ,
3183
+ "Cannot resolve \"parent\" type when class has no parent" );
3184
+ RETURN_THROWS ();
3185
+ }
3186
+ resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (intern -> ce -> parent -> name , allows_null , /* extra flags */ 0 );
3187
+ }
3172
3188
}
3173
3189
3174
3190
reflection_type_factory (resolved_type , return_value , /* legacy_behavior */ true, intern -> ce );
0 commit comments