Skip to content

Commit a85b760

Browse files
committed
improve (make magical) constructor support
1 parent 2ad56bd commit a85b760

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

Zend/tests/partial_function/object-constructor.phpt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ class Foo {
1414
$foo = new Foo(?, ?);
1515

1616
var_dump($foo);
17-
var_dump($foo(1,2));
17+
var_dump($first = $foo(1,2));
18+
var_dump($second = $foo(3,4));
19+
var_dump($first !== $second);
1820

1921
// Empty constructors
2022
class Bar {
@@ -47,10 +49,7 @@ catch (RuntimeException $e) {
4749

4850
?>
4951
--EXPECTF--
50-
object(Closure)#%d (3) {
51-
["this"]=>
52-
object(Foo)#%d (0) {
53-
}
52+
object(Closure)#%d (%d) {
5453
["parameter"]=>
5554
array(2) {
5655
["$one"]=>
@@ -69,7 +68,11 @@ object(Closure)#%d (3) {
6968
Rocking Foo::__construct [1, 2]
7069
object(Foo)#%d (0) {
7170
}
72-
object(Closure)#%d (2) {
71+
Rocking Foo::__construct [3, 4]
72+
object(Foo)#%d (0) {
73+
}
74+
bool(true)
75+
object(Closure)#%d (%d) {
7376
["this"]=>
7477
object(Bar)#%d (0) {
7578
}

Zend/zend_partial.c

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ typedef struct _zend_partial {
2727
zval This;
2828
zend_function func;
2929
zend_function trampoline;
30+
zend_class_entry *type;
3031
uint32_t argc;
3132
zval *argv;
3233
zend_array *named;
@@ -440,10 +441,25 @@ ZEND_NAMED_FUNCTION(zend_partial_call_magic)
440441
fci.params = ecalloc(sizeof(zval), fci.param_count);
441442
fcc.function_handler = &partial->func;
442443

443-
if (!Z_ISUNDEF(partial->This)) {
444+
445+
if (Z_TYPE(partial->This) == IS_OBJECT) {
444446
fci.object =
445447
fcc.object =
446448
zend_partial_this(Z_OBJ(partial->This));
449+
} else if (partial->type) {
450+
zval instance;
451+
452+
if (partial->type->create_object) {
453+
ZVAL_OBJ(&instance,
454+
partial->type->create_object(partial->type));
455+
} else {
456+
ZVAL_OBJ(&instance, zend_objects_new(partial->type));
457+
}
458+
459+
fci.object =
460+
fcc.object =
461+
Z_OBJ(instance);
462+
GC_ADD_FLAGS(fci.object, IS_OBJ_DESTRUCTOR_CALLED);
447463
}
448464

449465
memcpy(fci.params, partial->argv, partial->argc * sizeof(zval));
@@ -503,8 +519,7 @@ ZEND_NAMED_FUNCTION(zend_partial_call_magic)
503519
partial->func.internal_function.handler == zend_pass_function.handler)) {
504520
zval_ptr_dtor(return_value);
505521

506-
RETVAL_OBJ(
507-
Z_OBJ(partial->This));
522+
RETVAL_OBJ(fci.object);
508523
}
509524

510525
if (!fcc.function_handler) {
@@ -577,7 +592,18 @@ void zend_partial_apply(zval *result, zend_execute_data *call) {
577592
}
578593
}
579594

580-
ZVAL_COPY(&partial->This, &call->This);
595+
if (function->common.fn_flags & ZEND_ACC_CTOR) {
596+
partial->type = Z_OBJCE(call->This);
597+
598+
GC_ADD_FLAGS(
599+
Z_OBJ(call->This), IS_OBJ_DESTRUCTOR_CALLED);
600+
OBJ_RELEASE(Z_OBJ(call->This));
601+
602+
ZVAL_UNDEF(&partial->This);
603+
} else {
604+
ZVAL_COPY(&partial->This, &call->This);
605+
}
606+
581607

582608
memcpy(&partial->func, function,
583609
function->type == ZEND_INTERNAL_FUNCTION ?
@@ -592,8 +618,7 @@ void zend_partial_apply(zval *result, zend_execute_data *call) {
592618
}
593619

594620
if (partial->func.common.fn_flags & ZEND_ACC_CTOR) {
595-
GC_ADD_FLAGS(
596-
Z_OBJ(partial->This), IS_OBJ_DESTRUCTOR_CALLED);
621+
597622
}
598623

599624
if (partial->func.type == ZEND_USER_FUNCTION) {

0 commit comments

Comments
 (0)