Skip to content

Commit aaed3cc

Browse files
authored
Allow by-ref assign to WeakMap even if object is not yet in the map (#20097)
Previously this failed as the read_dimension which is invoked by ref-assign does not contain the logic to add the key, so it was required to first write the value using a normal assignment and then thereafter use the reference assignment. This solves it by adding the necessary logic to assign references directly.
1 parent ca78da4 commit aaed3cc

File tree

4 files changed

+34
-8
lines changed

4 files changed

+34
-8
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- Core:
66
. Added first-class callable cache to share instances for the duration of the
77
request. (ilutov)
8+
. It is now possible to use reference assign on WeakMap without the key
9+
needing to be present beforehand. (nielsdos)
810

911
- Intl:
1012
. Added IntlNumberRangeFormatter class to format an interval of two numbers

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ PHP 8.6 UPGRADE NOTES
2323
2. New Features
2424
========================================
2525

26+
- Core:
27+
. It is now possible to use reference assign on WeakMap without the key
28+
needing to be present beforehand.
29+
2630
- Intl:
2731
. Added IntlNumberRangeFormatter class to format an interval of two numbers with a given skeleton, locale, IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, IntlNumberRangeFormatter::COLLAPSE_ALL collapse and
2832
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY and
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
By-ref assign of WeakMap dimension
3+
--FILE--
4+
<?php
5+
$obj = new stdClass;
6+
$map = new WeakMap;
7+
$int = 0;
8+
$map[$obj] =& $int;
9+
$int++;
10+
var_dump($map[$obj]);
11+
?>
12+
--EXPECT--
13+
int(1)

Zend/zend_weakrefs.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -370,18 +370,25 @@ static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int
370370
zend_weakmap *wm = zend_weakmap_from(object);
371371
zend_object *obj_addr = Z_OBJ_P(offset);
372372
zval *zv = zend_hash_index_find(&wm->ht, zend_object_to_weakref_key(obj_addr));
373-
if (zv == NULL) {
374-
if (type != BP_VAR_IS) {
375-
zend_throw_error(NULL,
376-
"Object %s#%d not contained in WeakMap", ZSTR_VAL(obj_addr->ce->name), obj_addr->handle);
373+
if (type == BP_VAR_W || type == BP_VAR_RW) {
374+
if (zv == NULL) {
375+
zval value;
376+
zend_weakref_register(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP));
377+
ZVAL_NULL(&value);
378+
zv = zend_hash_index_add_new(&wm->ht, zend_object_to_weakref_key(obj_addr), &value);
379+
}
380+
ZVAL_MAKE_REF(zv);
381+
} else {
382+
if (zv == NULL) {
383+
if (type != BP_VAR_IS) {
384+
zend_throw_error(NULL,
385+
"Object %s#%d not contained in WeakMap", ZSTR_VAL(obj_addr->ce->name), obj_addr->handle);
386+
return NULL;
387+
}
377388
return NULL;
378389
}
379-
return NULL;
380390
}
381391

382-
if (type == BP_VAR_W || type == BP_VAR_RW) {
383-
ZVAL_MAKE_REF(zv);
384-
}
385392
return zv;
386393
}
387394

0 commit comments

Comments
 (0)