Skip to content

Commit 3f28b17

Browse files
committed
Add support for cloning WeakMaps
1 parent 5c229b2 commit 3f28b17

File tree

6 files changed

+35
-10
lines changed

6 files changed

+35
-10
lines changed

Zend/tests/weakrefs/weakmap_002.phpt renamed to Zend/tests/weakrefs/weakmap_error_conditions.phpt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,6 @@ try {
7777
} catch (Exception $e) {
7878
echo $e->getMessage(), "\n";
7979
}
80-
try {
81-
clone $map;
82-
} catch (Error $e) {
83-
echo $e->getMessage(), "\n";
84-
}
8580

8681
?>
8782
--EXPECT--
@@ -99,4 +94,3 @@ WeakMap objects do not support properties
9994
WeakMap objects do not support properties
10095
Serialization of 'WeakMap' is not allowed
10196
Unserialization of 'WeakMap' is not allowed
102-
Trying to clone an uncloneable object of class WeakMap

Zend/tests/weakrefs/weakmap_004.phpt renamed to Zend/tests/weakrefs/weakmap_multiple_weakrefs.phpt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ $map = new WeakMap;
1010
$map[$obj] = 1;
1111
$map2 = new WeakMap;
1212
$map2[$obj] = 1;
13+
$map3 = clone $map2;
1314

14-
var_dump($ref->get(), $map, $map2);
15+
var_dump($ref->get(), $map, $map2, $map3);
1516
unset($obj);
16-
var_dump($ref->get(), $map, $map2);
17+
var_dump($ref->get(), $map, $map2, $map3);
1718
unset($ref, $map, $map2);
1819

1920
$obj = new stdClass;
@@ -22,8 +23,9 @@ $map = new WeakMap;
2223
$map[$obj] = 1;
2324
$map2 = new WeakMap;
2425
$map2[$obj] = 1;
26+
$map3 = clone $map2;
2527

26-
unset($ref, $map, $map2);
28+
unset($ref, $map, $map2, $map3);
2729
var_dump($obj);
2830
unset($obj);
2931

@@ -51,10 +53,22 @@ object(WeakMap)#4 (1) {
5153
int(1)
5254
}
5355
}
56+
object(WeakMap)#5 (1) {
57+
[0]=>
58+
array(2) {
59+
["key"]=>
60+
object(stdClass)#1 (0) {
61+
}
62+
["value"]=>
63+
int(1)
64+
}
65+
}
5466
NULL
5567
object(WeakMap)#3 (0) {
5668
}
5769
object(WeakMap)#4 (0) {
5870
}
71+
object(WeakMap)#5 (0) {
72+
}
5973
object(stdClass)#4 (0) {
6074
}

Zend/zend_weakrefs.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,23 @@ static HashTable *zend_weakmap_get_gc(zend_object *object, zval **table, int *n)
460460
return &wm->ht;
461461
}
462462

463+
static zend_object *zend_weakmap_clone_obj(zend_object *old_object)
464+
{
465+
zend_object *new_object = zend_weakmap_create_object(zend_ce_weakmap);
466+
zend_weakmap *old_wm = zend_weakmap_from(old_object);
467+
zend_weakmap *new_wm = zend_weakmap_from(new_object);
468+
zend_hash_copy(&new_wm->ht, &old_wm->ht, NULL);
469+
470+
zend_ulong obj_addr;
471+
zval *val;
472+
ZEND_HASH_FOREACH_NUM_KEY_VAL(&new_wm->ht, obj_addr, val) {
473+
zend_weakref_register(
474+
(zend_object *) obj_addr, ZEND_WEAKREF_ENCODE(new_wm, ZEND_WEAKREF_TAG_MAP));
475+
zval_add_ref(val);
476+
} ZEND_HASH_FOREACH_END();
477+
return new_object;
478+
}
479+
463480
static HashPosition *zend_weakmap_iterator_get_pos_ptr(zend_weakmap_iterator *iter) {
464481
ZEND_ASSERT(iter->ht_iter != (uint32_t) -1);
465482
return &EG(ht_iterators)[iter->ht_iter].pos;
@@ -658,12 +675,12 @@ void zend_register_weakref_ce(void) /* {{{ */
658675
zend_weakmap_handlers.count_elements = zend_weakmap_count_elements;
659676
zend_weakmap_handlers.get_properties_for = zend_weakmap_get_properties_for;
660677
zend_weakmap_handlers.get_gc = zend_weakmap_get_gc;
678+
zend_weakmap_handlers.clone_obj = zend_weakmap_clone_obj;
661679
zend_weakmap_handlers.read_property = zend_weakref_no_read;
662680
zend_weakmap_handlers.write_property = zend_weakref_no_write;
663681
zend_weakmap_handlers.has_property = zend_weakref_no_isset;
664682
zend_weakmap_handlers.unset_property = zend_weakref_no_unset;
665683
zend_weakmap_handlers.get_property_ptr_ptr = zend_weakref_no_read_ptr;
666-
zend_weakmap_handlers.clone_obj = NULL;
667684
}
668685
/* }}} */
669686

0 commit comments

Comments
 (0)