Skip to content

Commit 5854352

Browse files
committed
Implement WeakMap
1 parent 2f8b766 commit 5854352

8 files changed

+1056
-25
lines changed

Zend/tests/weakrefs/weakmap_001.phpt

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
--TEST--
2+
Basic WeakMap behavior (as a map)
3+
--FILE--
4+
<?php
5+
6+
$map = new WeakMap;
7+
var_dump(count($map));
8+
9+
$obj = new stdClass;
10+
$obj->value = 1;
11+
$obj2 = new stdClass;
12+
$obj2->value = 2;
13+
14+
$map[$obj] = $obj2;
15+
var_dump(count($map));
16+
var_dump($map);
17+
var_dump(isset($map[$obj]));
18+
var_dump(!empty($map[$obj]));
19+
var_dump($map[$obj]);
20+
21+
$map[$obj] = 42;
22+
var_dump($map);
23+
var_dump(isset($map[$obj]));
24+
var_dump(!empty($map[$obj]));
25+
var_dump($map[$obj]);
26+
27+
$map[$obj] = false;
28+
var_dump($map);
29+
var_dump(isset($map[$obj]));
30+
var_dump(!empty($map[$obj]));
31+
var_dump($map[$obj]);
32+
33+
$map[$obj] = null;
34+
var_dump($map);
35+
var_dump(isset($map[$obj]));
36+
var_dump(!empty($map[$obj]));
37+
var_dump($map[$obj]);
38+
39+
unset($map[$obj]);
40+
var_dump($map);
41+
var_dump(isset($map[$obj]));
42+
var_dump(!empty($map[$obj]));
43+
try {
44+
var_dump($map[$obj]);
45+
} catch (Error $e) {
46+
echo $e->getMessage(), "\n";
47+
}
48+
49+
echo "\nIndirect modification:\n";
50+
$map[$obj] = [];
51+
$map[$obj][] = 42;
52+
$map[$obj2] = 41;
53+
$map[$obj2]++;
54+
var_dump($map);
55+
56+
echo "\nMethods:\n";
57+
var_dump($map->offsetSet($obj2, 43));
58+
var_dump($map->offsetGet($obj2));
59+
var_dump($map->offsetExists($obj2));
60+
var_dump($map->count());
61+
var_dump($map->offsetUnset($obj2));
62+
var_dump($map->count());
63+
64+
?>
65+
--EXPECT--
66+
int(0)
67+
int(1)
68+
object(WeakMap)#1 (1) {
69+
[0]=>
70+
array(2) {
71+
["key"]=>
72+
object(stdClass)#2 (1) {
73+
["value"]=>
74+
int(1)
75+
}
76+
["value"]=>
77+
object(stdClass)#3 (1) {
78+
["value"]=>
79+
int(2)
80+
}
81+
}
82+
}
83+
bool(true)
84+
bool(true)
85+
object(stdClass)#3 (1) {
86+
["value"]=>
87+
int(2)
88+
}
89+
object(WeakMap)#1 (1) {
90+
[0]=>
91+
array(2) {
92+
["key"]=>
93+
object(stdClass)#2 (1) {
94+
["value"]=>
95+
int(1)
96+
}
97+
["value"]=>
98+
int(42)
99+
}
100+
}
101+
bool(true)
102+
bool(true)
103+
int(42)
104+
object(WeakMap)#1 (1) {
105+
[0]=>
106+
array(2) {
107+
["key"]=>
108+
object(stdClass)#2 (1) {
109+
["value"]=>
110+
int(1)
111+
}
112+
["value"]=>
113+
bool(false)
114+
}
115+
}
116+
bool(true)
117+
bool(false)
118+
bool(false)
119+
object(WeakMap)#1 (1) {
120+
[0]=>
121+
array(2) {
122+
["key"]=>
123+
object(stdClass)#2 (1) {
124+
["value"]=>
125+
int(1)
126+
}
127+
["value"]=>
128+
NULL
129+
}
130+
}
131+
bool(false)
132+
bool(false)
133+
NULL
134+
object(WeakMap)#1 (0) {
135+
}
136+
bool(false)
137+
bool(false)
138+
Object stdClass#2 not contained in WeakMap
139+
140+
Indirect modification:
141+
object(WeakMap)#1 (2) {
142+
[0]=>
143+
array(2) {
144+
["key"]=>
145+
object(stdClass)#2 (1) {
146+
["value"]=>
147+
int(1)
148+
}
149+
["value"]=>
150+
array(1) {
151+
[0]=>
152+
int(42)
153+
}
154+
}
155+
[1]=>
156+
array(2) {
157+
["key"]=>
158+
object(stdClass)#3 (1) {
159+
["value"]=>
160+
int(2)
161+
}
162+
["value"]=>
163+
int(42)
164+
}
165+
}
166+
167+
Methods:
168+
NULL
169+
int(43)
170+
bool(true)
171+
int(2)
172+
NULL
173+
int(1)

Zend/tests/weakrefs/weakmap_002.phpt

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
--TEST--
2+
WeakMap error conditions
3+
--FILE--
4+
<?php
5+
6+
$map = new WeakMap;
7+
try {
8+
$map[1] = 2;
9+
} catch (TypeError $e) {
10+
echo $e->getMessage(), "\n";
11+
}
12+
try {
13+
var_dump($map[1]);
14+
} catch (TypeError $e) {
15+
echo $e->getMessage(), "\n";
16+
}
17+
try {
18+
isset($map[1]);
19+
} catch (TypeError $e) {
20+
echo $e->getMessage(), "\n";
21+
}
22+
try {
23+
unset($map[1]);
24+
} catch (TypeError $e) {
25+
echo $e->getMessage(), "\n";
26+
}
27+
28+
try {
29+
$map[] = 1;
30+
} catch (Error $e) {
31+
echo $e->getMessage(), "\n";
32+
}
33+
try {
34+
$map[][1] = 1;
35+
} catch (Error $e) {
36+
echo $e->getMessage(), "\n";
37+
}
38+
try {
39+
var_dump($map[new stdClass]);
40+
} catch (Error $e) {
41+
echo $e->getMessage(), "\n";
42+
}
43+
44+
try {
45+
$map->prop = 1;
46+
} catch (Error $e) {
47+
echo $e->getMessage(), "\n";
48+
}
49+
try {
50+
var_dump($map->prop);
51+
} catch (Error $e) {
52+
echo $e->getMessage(), "\n";
53+
}
54+
try {
55+
$r =& $map->prop;
56+
} catch (Error $e) {
57+
echo $e->getMessage(), "\n";
58+
}
59+
try {
60+
isset($map->prop);
61+
} catch (Error $e) {
62+
echo $e->getMessage(), "\n";
63+
}
64+
try {
65+
unset($map->prop);
66+
} catch (Error $e) {
67+
echo $e->getMessage(), "\n";
68+
}
69+
70+
try {
71+
serialize($map);
72+
} catch (Exception $e) {
73+
echo $e->getMessage(), "\n";
74+
}
75+
try {
76+
unserialize('C:7:"WeakMap":0:{}');
77+
} catch (Exception $e) {
78+
echo $e->getMessage(), "\n";
79+
}
80+
try {
81+
clone $map;
82+
} catch (Error $e) {
83+
echo $e->getMessage(), "\n";
84+
}
85+
86+
?>
87+
--EXPECT--
88+
WeakMap key must be an object
89+
WeakMap key must be an object
90+
WeakMap key must be an object
91+
WeakMap key must be an object
92+
Cannot append to WeakMap
93+
Cannot append to WeakMap
94+
Object stdClass#2 not contained in WeakMap
95+
WeakMap objects do not support properties
96+
WeakMap objects do not support properties
97+
WeakMap objects do not support property references
98+
WeakMap objects do not support properties
99+
WeakMap objects do not support properties
100+
Serialization of 'WeakMap' is not allowed
101+
Unserialization of 'WeakMap' is not allowed
102+
Trying to clone an uncloneable object of class WeakMap

Zend/tests/weakrefs/weakmap_003.phpt

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
--TEST--
2+
The weak part of the WeakMap
3+
--FILE--
4+
<?php
5+
6+
$map = new WeakMap;
7+
8+
// This is doing to be inserted into the map and immediately removed again
9+
$map[new stdClass] = 1;
10+
var_dump($map);
11+
12+
$obj = new stdClass;
13+
$map[$obj] = 2;
14+
var_dump($map);
15+
16+
unset($obj);
17+
var_dump($map);
18+
19+
echo "\nDestructor in WeakMap value:\n";
20+
$obj = new stdClass;
21+
$map[$obj] = new class {
22+
public function __destruct() {
23+
echo "Dtor!\n";
24+
}
25+
};
26+
27+
echo "Before unset:\n";
28+
unset($obj);
29+
echo "After unset:\n";
30+
var_dump($map);
31+
32+
echo "\nDestroying map with live object:\n";
33+
$obj = new stdClass;
34+
$map[$obj] = 3;
35+
unset($map);
36+
var_dump($obj);
37+
38+
echo "\nObject freed by GC:\n";
39+
$map = new WeakMap;
40+
$obj = new stdClass;
41+
$obj->obj = $obj;
42+
$map[$obj] = 4;
43+
unset($obj);
44+
var_dump($map);
45+
gc_collect_cycles();
46+
var_dump($map);
47+
48+
echo "\nStoring map in itself:\n";
49+
$map = new WeakMap;
50+
$map[$map] = $map;
51+
var_dump($map);
52+
unset($map);
53+
54+
?>
55+
--EXPECT--
56+
object(WeakMap)#1 (0) {
57+
}
58+
object(WeakMap)#1 (1) {
59+
[0]=>
60+
array(2) {
61+
["key"]=>
62+
object(stdClass)#2 (0) {
63+
}
64+
["value"]=>
65+
int(2)
66+
}
67+
}
68+
object(WeakMap)#1 (0) {
69+
}
70+
71+
Destructor in WeakMap value:
72+
Before unset:
73+
Dtor!
74+
After unset:
75+
object(WeakMap)#1 (0) {
76+
}
77+
78+
Destroying map with live object:
79+
object(stdClass)#2 (0) {
80+
}
81+
82+
Object freed by GC:
83+
object(WeakMap)#1 (1) {
84+
[0]=>
85+
array(2) {
86+
["key"]=>
87+
object(stdClass)#3 (1) {
88+
["obj"]=>
89+
*RECURSION*
90+
}
91+
["value"]=>
92+
int(4)
93+
}
94+
}
95+
object(WeakMap)#1 (0) {
96+
}
97+
98+
Storing map in itself:
99+
object(WeakMap)#3 (1) {
100+
[0]=>
101+
array(2) {
102+
["key"]=>
103+
*RECURSION*
104+
["value"]=>
105+
*RECURSION*
106+
}
107+
}

0 commit comments

Comments
 (0)