Skip to content

Commit 349db0e

Browse files
committed
add unset support and more tests
1 parent c18ea45 commit 349db0e

File tree

5 files changed

+184
-10
lines changed

5 files changed

+184
-10
lines changed

Zend/tests/data_class_007.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Private properties are included in equality checks
3+
--FILE--
4+
<?php
5+
6+
data class Length {
7+
public function __construct(private float $length) {}
8+
}
9+
10+
$l1 = new Length(1.0);
11+
$l2 = new Length(1.0);
12+
$l3 = new Length(2.0);
13+
var_dump($l1 === $l2);
14+
var_dump($l1 !== $l3);
15+
?>
16+
--EXPECT--
17+
bool(true)
18+
bool(true)

Zend/tests/data_class_008.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Data classes can be anonymous
3+
--FILE--
4+
<?php
5+
6+
$data = new data class(1) {
7+
public function __construct(private int $value) {}
8+
};
9+
10+
var_dump($data);
11+
?>
12+
--EXPECT--
13+
data object(class@anonymous)#1 (1) {
14+
["value":"class@anonymous":private]=>
15+
int(1)
16+
}

Zend/tests/data_class_009.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
unset triggers copy-on-write
3+
--FILE--
4+
<?php
5+
6+
$data = new data class(1) {
7+
public function __construct(public int $value) {}
8+
};
9+
10+
$copy = $data;
11+
unset($copy->value);
12+
var_dump($data !== $copy);
13+
var_dump($data);
14+
?>
15+
--EXPECT--
16+
bool(true)
17+
data object(class@anonymous)#1 (1) {
18+
["value"]=>
19+
int(1)
20+
}

Zend/zend_vm_def.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6863,7 +6863,19 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
68636863
break;
68646864
}
68656865
}
6866-
Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
6866+
// if this is a data class, we may need to CoW
6867+
zend_object *zobj = Z_OBJ_P(container);
6868+
if (zobj->ce->ce_flags & ZEND_ACC_DATA_CLASS) {
6869+
if (GC_REFCOUNT(zobj) > 1) {
6870+
// clone the object
6871+
zend_object *new_obj = zend_objects_clone_obj(zobj);
6872+
// set the object zval to the new object
6873+
ZVAL_OBJ(container, new_obj);
6874+
GC_DELREF(zobj);
6875+
zobj = new_obj;
6876+
}
6877+
}
6878+
Z_OBJ_HT_P(container)->unset_property(zobj, name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
68676879
if (OP2_TYPE != IS_CONST) {
68686880
zend_tmp_string_release(tmp_name);
68696881
}

Zend/zend_vm_execute.h

Lines changed: 117 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)