1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 08:12:21 +01:00

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.
This commit is contained in:
Niels Dossche
2025-10-08 17:37:24 +02:00
committed by GitHub
parent ca78da4888
commit aaed3ccb47
4 changed files with 34 additions and 8 deletions

2
NEWS
View File

@@ -5,6 +5,8 @@ PHP NEWS
- Core:
. Added first-class callable cache to share instances for the duration of the
request. (ilutov)
. It is now possible to use reference assign on WeakMap without the key
needing to be present beforehand. (nielsdos)
- Intl:
. Added IntlNumberRangeFormatter class to format an interval of two numbers

View File

@@ -23,6 +23,10 @@ PHP 8.6 UPGRADE NOTES
2. New Features
========================================
- Core:
. It is now possible to use reference assign on WeakMap without the key
needing to be present beforehand.
- Intl:
. 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
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY and

View File

@@ -0,0 +1,13 @@
--TEST--
By-ref assign of WeakMap dimension
--FILE--
<?php
$obj = new stdClass;
$map = new WeakMap;
$int = 0;
$map[$obj] =& $int;
$int++;
var_dump($map[$obj]);
?>
--EXPECT--
int(1)

View File

@@ -370,18 +370,25 @@ static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int
zend_weakmap *wm = zend_weakmap_from(object);
zend_object *obj_addr = Z_OBJ_P(offset);
zval *zv = zend_hash_index_find(&wm->ht, zend_object_to_weakref_key(obj_addr));
if (zv == NULL) {
if (type != BP_VAR_IS) {
zend_throw_error(NULL,
"Object %s#%d not contained in WeakMap", ZSTR_VAL(obj_addr->ce->name), obj_addr->handle);
if (type == BP_VAR_W || type == BP_VAR_RW) {
if (zv == NULL) {
zval value;
zend_weakref_register(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP));
ZVAL_NULL(&value);
zv = zend_hash_index_add_new(&wm->ht, zend_object_to_weakref_key(obj_addr), &value);
}
ZVAL_MAKE_REF(zv);
} else {
if (zv == NULL) {
if (type != BP_VAR_IS) {
zend_throw_error(NULL,
"Object %s#%d not contained in WeakMap", ZSTR_VAL(obj_addr->ce->name), obj_addr->handle);
return NULL;
}
return NULL;
}
return NULL;
}
if (type == BP_VAR_W || type == BP_VAR_RW) {
ZVAL_MAKE_REF(zv);
}
return zv;
}