diff --git a/php_phongo.c b/php_phongo.c index 0691c176e..ec12b8318 100644 --- a/php_phongo.c +++ b/php_phongo.c @@ -155,13 +155,6 @@ static zend_class_entry* php_phongo_fetch_internal_class(const char* class_name, return NULL; } -static HashTable* php_phongo_std_get_gc(zend_object* object, zval** table, int* n) -{ - *table = NULL; - *n = 0; - return zend_std_get_properties(object); -} - PHP_MINIT_FUNCTION(mongodb) /* {{{ */ { bson_mem_vtable_t bson_mem_vtable = { @@ -197,9 +190,6 @@ PHP_MINIT_FUNCTION(mongodb) /* {{{ */ /* Disable cloning by default. Individual classes can opt in if they need to * support this (e.g. BSON objects). */ phongo_std_object_handlers.clone_obj = NULL; - /* Ensure that get_gc delegates to zend_std_get_properties directly in case - * our class defines a get_properties handler for debugging purposes. */ - phongo_std_object_handlers.get_gc = php_phongo_std_get_gc; /* Initialize zend_class_entry dependencies. * diff --git a/php_phongo.h b/php_phongo.h index d0655f911..ccffb5f8a 100644 --- a/php_phongo.h +++ b/php_phongo.h @@ -77,11 +77,106 @@ zend_object_handlers* phongo_get_std_object_handlers(void); #define PHONGO_GET_PROPERTY_HASH_FREE_PROPS(is_temp, props) \ do { \ if (is_temp) { \ - zend_hash_destroy((props)); \ - FREE_HASHTABLE(props); \ + zend_hash_release((props)); \ } \ } while (0) +#define PHONGO_ASSIGN_PROPERTY_HANDLERS(_name) \ + do { \ + php_phongo_handler_##_name.read_property = php_phongo_##_name##_read_property; \ + php_phongo_handler_##_name.write_property = php_phongo_##_name##_write_property; \ + php_phongo_handler_##_name.has_property = php_phongo_##_name##_has_property; \ + php_phongo_handler_##_name.unset_property = php_phongo_##_name##_unset_property; \ + php_phongo_handler_##_name.get_property_ptr_ptr = php_phongo_##_name##_get_property_ptr_ptr; \ + php_phongo_handler_##_name.get_gc = php_phongo_##_name##_get_gc; \ + } while (0) + +#define PHONGO_DEFINE_PROPERTY_HANDLERS(_name, _intern_extractor) \ + static zval* php_phongo_##_name##_read_property(zend_object* zobj, zend_string* member, int type, void** cache_slot, zval* rv) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + zval* ret = zend_hash_find(props, member); \ + if (ret) { \ + return ret; \ + } \ + return &EG(uninitialized_zval); \ + } \ + \ + static zval* php_phongo_##_name##_write_property(zend_object* zobj, zend_string* name, zval* value, void** cache_slot) \ + { \ + Z_TRY_ADDREF_P(value); \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + return zend_hash_add_new(props, name, value); \ + } \ + \ + static int php_phongo_##_name##_has_property(zend_object* zobj, zend_string* name, int has_set_exists, void** cache_slot) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + zval* value = zend_hash_find(props, name); \ + if (value) { \ + if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY) { \ + return zend_is_true(value); \ + } \ + if (has_set_exists < ZEND_PROPERTY_NOT_EMPTY) { \ + ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_ISSET); \ + ZVAL_DEREF(value); \ + return (Z_TYPE_P(value) != IS_NULL); \ + } \ + ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_EXISTS); \ + return true; \ + } \ + return false; \ + } \ + \ + static void php_phongo_##_name##_unset_property(zend_object* zobj, zend_string* name, void** cache_slot) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + zend_hash_del(props, name); \ + } \ + \ + static zval* php_phongo_##_name##_get_property_ptr_ptr(zend_object* zobj, zend_string* name, int type, void** cache_slot) \ + { \ + HashTable* props = _intern_extractor(zobj)->php_properties; \ + if (!props) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \ + _intern_extractor(zobj)->php_properties = props; \ + } \ + \ + zval* value = zend_hash_find(props, name); \ + if (value) { \ + return value; \ + } \ + return zend_hash_add(props, name, &EG(uninitialized_zval)); \ + } \ + \ + static HashTable* php_phongo_##_name##_get_gc(zend_object* zobj, zval** table, int* n) \ + { \ + *table = NULL; \ + *n = 0; \ + return _intern_extractor(zobj)->php_properties; \ + } + #define PHONGO_ZVAL_EXCEPTION_NAME(e) (ZSTR_VAL(e->ce->name)) #define PHONGO_SET_CREATED_BY_PID(intern) \ diff --git a/src/BSON/Binary.c b/src/BSON/Binary.c index 64fc4a90a..add99aa42 100644 --- a/src/BSON/Binary.c +++ b/src/BSON/Binary.c @@ -225,8 +225,11 @@ static void php_phongo_binary_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -320,6 +323,8 @@ static HashTable* php_phongo_binary_get_properties(zend_object* object) return php_phongo_binary_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(binary, Z_OBJ_BINARY); + void php_phongo_binary_init_ce(INIT_FUNC_ARGS) { php_phongo_binary_ce = register_class_MongoDB_BSON_Binary(php_phongo_binary_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -332,6 +337,8 @@ void php_phongo_binary_init_ce(INIT_FUNC_ARGS) php_phongo_handler_binary.get_properties = php_phongo_binary_get_properties; php_phongo_handler_binary.free_obj = php_phongo_binary_free_object; php_phongo_handler_binary.offset = XtOffsetOf(php_phongo_binary_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(binary); } bool phongo_binary_new(zval* object, const char* data, size_t data_len, bson_subtype_t type) diff --git a/src/BSON/DBPointer.c b/src/BSON/DBPointer.c index b0285732e..50d84ac82 100644 --- a/src/BSON/DBPointer.c +++ b/src/BSON/DBPointer.c @@ -177,8 +177,11 @@ static void php_phongo_dbpointer_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -241,6 +244,8 @@ static HashTable* php_phongo_dbpointer_get_properties(zend_object* object) return php_phongo_dbpointer_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(dbpointer, Z_OBJ_DBPOINTER); + void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS) { php_phongo_dbpointer_ce = register_class_MongoDB_BSON_DBPointer(php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -253,6 +258,8 @@ void php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS) php_phongo_handler_dbpointer.get_properties = php_phongo_dbpointer_get_properties; php_phongo_handler_dbpointer.free_obj = php_phongo_dbpointer_free_object; php_phongo_handler_dbpointer.offset = XtOffsetOf(php_phongo_dbpointer_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(dbpointer); } bool phongo_dbpointer_new(zval* object, const char* ref, size_t ref_len, const bson_oid_t* oid) diff --git a/src/BSON/Decimal128.c b/src/BSON/Decimal128.c index 970ee00e7..0b2ef581b 100644 --- a/src/BSON/Decimal128.c +++ b/src/BSON/Decimal128.c @@ -169,8 +169,11 @@ static void php_phongo_decimal128_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -216,6 +219,8 @@ static HashTable* php_phongo_decimal128_get_properties(zend_object* object) return php_phongo_decimal128_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(decimal128, Z_OBJ_DECIMAL128) + void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) { php_phongo_decimal128_ce = register_class_MongoDB_BSON_Decimal128(php_phongo_decimal128_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -227,6 +232,8 @@ void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties; php_phongo_handler_decimal128.free_obj = php_phongo_decimal128_free_object; php_phongo_handler_decimal128.offset = XtOffsetOf(php_phongo_decimal128_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(decimal128); } bool phongo_decimal128_new(zval* object, const bson_decimal128_t* decimal) diff --git a/src/BSON/Document.c b/src/BSON/Document.c index b0886b369..675b99a20 100644 --- a/src/BSON/Document.c +++ b/src/BSON/Document.c @@ -447,8 +447,7 @@ static void php_phongo_document_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } } diff --git a/src/BSON/Int64.c b/src/BSON/Int64.c index d350f2b7b..f859a61d3 100644 --- a/src/BSON/Int64.c +++ b/src/BSON/Int64.c @@ -176,8 +176,11 @@ static void php_phongo_int64_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -554,6 +557,8 @@ static HashTable* php_phongo_int64_get_properties(zend_object* object) return php_phongo_int64_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(int64, Z_OBJ_INT64) + void php_phongo_int64_init_ce(INIT_FUNC_ARGS) { php_phongo_int64_ce = register_class_MongoDB_BSON_Int64(php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -568,6 +573,8 @@ void php_phongo_int64_init_ce(INIT_FUNC_ARGS) php_phongo_handler_int64.offset = XtOffsetOf(php_phongo_int64_t, std); php_phongo_handler_int64.cast_object = php_phongo_int64_cast_object; php_phongo_handler_int64.do_operation = php_phongo_int64_do_operation; + + PHONGO_ASSIGN_PROPERTY_HANDLERS(int64); } bool phongo_int64_new(zval* object, int64_t integer) diff --git a/src/BSON/Iterator.c b/src/BSON/Iterator.c index 416e103b1..14dbf0a7a 100644 --- a/src/BSON/Iterator.c +++ b/src/BSON/Iterator.c @@ -249,8 +249,11 @@ static void php_phongo_iterator_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } php_phongo_iterator_free_current(intern); @@ -378,6 +381,8 @@ static zend_object_iterator* php_phongo_iterator_get_iterator(zend_class_entry* return iterator; } +PHONGO_DEFINE_PROPERTY_HANDLERS(iterator, Z_OBJ_ITERATOR) + void php_phongo_iterator_init_ce(INIT_FUNC_ARGS) { php_phongo_iterator_ce = register_class_MongoDB_BSON_Iterator(zend_ce_iterator); @@ -390,4 +395,6 @@ void php_phongo_iterator_init_ce(INIT_FUNC_ARGS) php_phongo_handler_iterator.get_properties = php_phongo_iterator_get_properties; php_phongo_handler_iterator.free_obj = php_phongo_iterator_free_object; php_phongo_handler_iterator.offset = XtOffsetOf(php_phongo_iterator_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(iterator); } diff --git a/src/BSON/Javascript.c b/src/BSON/Javascript.c index 38312dc2d..97cd94893 100644 --- a/src/BSON/Javascript.c +++ b/src/BSON/Javascript.c @@ -257,14 +257,18 @@ static void php_phongo_javascript_free_object(zend_object* object) if (intern->code) { efree(intern->code); } + if (intern->scope) { bson_destroy(intern->scope); intern->scope = NULL; } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -322,6 +326,8 @@ static HashTable* php_phongo_javascript_get_properties(zend_object* object) return php_phongo_javascript_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(javascript, Z_OBJ_JAVASCRIPT) + void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) { php_phongo_javascript_ce = register_class_MongoDB_BSON_Javascript(php_phongo_javascript_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -334,6 +340,8 @@ void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) php_phongo_handler_javascript.get_properties = php_phongo_javascript_get_properties; php_phongo_handler_javascript.free_obj = php_phongo_javascript_free_object; php_phongo_handler_javascript.offset = XtOffsetOf(php_phongo_javascript_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(javascript); } bool phongo_javascript_new(zval* object, const char* code, size_t code_len, const bson_t* scope) diff --git a/src/BSON/ObjectId.c b/src/BSON/ObjectId.c index 240441ac4..3a2f8ed15 100644 --- a/src/BSON/ObjectId.c +++ b/src/BSON/ObjectId.c @@ -203,8 +203,11 @@ static void php_phongo_objectid_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -263,6 +266,8 @@ static HashTable* php_phongo_objectid_get_properties(zend_object* object) return php_phongo_objectid_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(objectid, Z_OBJ_OBJECTID) + void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) { php_phongo_objectid_ce = register_class_MongoDB_BSON_ObjectId(php_phongo_objectid_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -275,6 +280,8 @@ void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) php_phongo_handler_objectid.get_properties = php_phongo_objectid_get_properties; php_phongo_handler_objectid.free_obj = php_phongo_objectid_free_object; php_phongo_handler_objectid.offset = XtOffsetOf(php_phongo_objectid_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(objectid); } bool phongo_objectid_new(zval* return_value, const bson_oid_t* oid) diff --git a/src/BSON/PackedArray.c b/src/BSON/PackedArray.c index 6fdbcf575..f87d00cab 100644 --- a/src/BSON/PackedArray.c +++ b/src/BSON/PackedArray.c @@ -431,8 +431,11 @@ static void php_phongo_packedarray_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -564,6 +567,8 @@ void php_phongo_packedarray_unset_dimension(zend_object* object, zval* offset) phongo_throw_exception(PHONGO_ERROR_LOGIC, "Cannot unset %s offset", ZSTR_VAL(php_phongo_packedarray_ce->name)); } +PHONGO_DEFINE_PROPERTY_HANDLERS(packedarray, Z_OBJ_PACKEDARRAY) + void php_phongo_packedarray_init_ce(INIT_FUNC_ARGS) { php_phongo_packedarray_ce = register_class_MongoDB_BSON_PackedArray(zend_ce_aggregate, zend_ce_arrayaccess, php_phongo_type_ce, zend_ce_stringable); @@ -580,6 +585,8 @@ void php_phongo_packedarray_init_ce(INIT_FUNC_ARGS) php_phongo_handler_packedarray.has_dimension = php_phongo_packedarray_has_dimension; php_phongo_handler_packedarray.unset_dimension = php_phongo_packedarray_unset_dimension; php_phongo_handler_packedarray.offset = XtOffsetOf(php_phongo_packedarray_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(packedarray); } bool phongo_packedarray_new(zval* object, bson_t* bson, bool copy) diff --git a/src/BSON/Regex.c b/src/BSON/Regex.c index a75b75e39..fcfc829c4 100644 --- a/src/BSON/Regex.c +++ b/src/BSON/Regex.c @@ -229,8 +229,11 @@ static void php_phongo_regex_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -294,6 +297,8 @@ static HashTable* php_phongo_regex_get_properties(zend_object* object) return php_phongo_regex_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(regex, Z_OBJ_REGEX) + void php_phongo_regex_init_ce(INIT_FUNC_ARGS) { php_phongo_regex_ce = register_class_MongoDB_BSON_Regex(php_phongo_regex_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -306,6 +311,8 @@ void php_phongo_regex_init_ce(INIT_FUNC_ARGS) php_phongo_handler_regex.get_properties = php_phongo_regex_get_properties; php_phongo_handler_regex.free_obj = php_phongo_regex_free_object; php_phongo_handler_regex.offset = XtOffsetOf(php_phongo_regex_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(regex); } bool phongo_regex_new(zval* object, const char* pattern, const char* flags) diff --git a/src/BSON/Symbol.c b/src/BSON/Symbol.c index a47b6c2fe..d2c28171c 100644 --- a/src/BSON/Symbol.c +++ b/src/BSON/Symbol.c @@ -151,8 +151,11 @@ static void php_phongo_symbol_free_object(zend_object* object) } if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -208,6 +211,8 @@ static HashTable* php_phongo_symbol_get_properties(zend_object* object) return php_phongo_symbol_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(symbol, Z_OBJ_SYMBOL) + void php_phongo_symbol_init_ce(INIT_FUNC_ARGS) { php_phongo_symbol_ce = register_class_MongoDB_BSON_Symbol(php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -220,6 +225,8 @@ void php_phongo_symbol_init_ce(INIT_FUNC_ARGS) php_phongo_handler_symbol.get_properties = php_phongo_symbol_get_properties; php_phongo_handler_symbol.free_obj = php_phongo_symbol_free_object; php_phongo_handler_symbol.offset = XtOffsetOf(php_phongo_symbol_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(symbol); } bool phongo_symbol_new(zval* object, const char* symbol, size_t symbol_len) diff --git a/src/BSON/Timestamp.c b/src/BSON/Timestamp.c index 82cd6f537..f646b6757 100644 --- a/src/BSON/Timestamp.c +++ b/src/BSON/Timestamp.c @@ -262,8 +262,11 @@ static void php_phongo_timestamp_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -328,6 +331,8 @@ static HashTable* php_phongo_timestamp_get_properties(zend_object* object) return php_phongo_timestamp_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(timestamp, Z_OBJ_TIMESTAMP); + void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) { php_phongo_timestamp_ce = register_class_MongoDB_BSON_Timestamp(php_phongo_timestamp_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -340,6 +345,8 @@ void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties; php_phongo_handler_timestamp.free_obj = php_phongo_timestamp_free_object; php_phongo_handler_timestamp.offset = XtOffsetOf(php_phongo_timestamp_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(timestamp); } bool phongo_timestamp_new(zval* object, uint32_t increment, uint32_t timestamp) diff --git a/src/BSON/UTCDateTime.c b/src/BSON/UTCDateTime.c index d0f169858..6655ad5d8 100644 --- a/src/BSON/UTCDateTime.c +++ b/src/BSON/UTCDateTime.c @@ -302,8 +302,11 @@ static void php_phongo_utcdatetime_free_object(zend_object* object) zend_object_std_dtor(&intern->std); if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); + } + + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -363,6 +366,8 @@ static HashTable* php_phongo_utcdatetime_get_properties(zend_object* object) return php_phongo_utcdatetime_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(utcdatetime, Z_OBJ_UTCDATETIME) + void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) { php_phongo_utcdatetime_ce = register_class_MongoDB_BSON_UTCDateTime(php_phongo_utcdatetime_interface_ce, php_phongo_json_serializable_ce, php_phongo_type_ce, zend_ce_stringable); @@ -375,6 +380,8 @@ void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties; php_phongo_handler_utcdatetime.free_obj = php_phongo_utcdatetime_free_object; php_phongo_handler_utcdatetime.offset = XtOffsetOf(php_phongo_utcdatetime_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(utcdatetime); } bool phongo_utcdatetime_new(zval* object, int64_t msec_since_epoch) diff --git a/src/MongoDB/Manager.c b/src/MongoDB/Manager.c index 2bf02fbdf..b3846bba0 100644 --- a/src/MongoDB/Manager.c +++ b/src/MongoDB/Manager.c @@ -798,8 +798,7 @@ static void php_phongo_manager_free_object(zend_object* object) } if (intern->subscribers) { - zend_hash_destroy(intern->subscribers); - FREE_HASHTABLE(intern->subscribers); + zend_hash_release(intern->subscribers); } } diff --git a/src/MongoDB/ReadConcern.c b/src/MongoDB/ReadConcern.c index 54ed384db..34dbd3d57 100644 --- a/src/MongoDB/ReadConcern.c +++ b/src/MongoDB/ReadConcern.c @@ -183,13 +183,16 @@ static void php_phongo_readconcern_free_object(zend_object* object) zend_object_std_dtor(&intern->std); + if (intern->read_concern) { + mongoc_read_concern_destroy(intern->read_concern); + } + if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } - if (intern->read_concern) { - mongoc_read_concern_destroy(intern->read_concern); + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -216,6 +219,8 @@ static HashTable* php_phongo_readconcern_get_properties(zend_object* object) return php_phongo_readconcern_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(readconcern, Z_OBJ_READCONCERN) + void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS) { php_phongo_readconcern_ce = register_class_MongoDB_Driver_ReadConcern(php_phongo_serializable_ce); @@ -226,6 +231,8 @@ void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS) php_phongo_handler_readconcern.get_properties = php_phongo_readconcern_get_properties; php_phongo_handler_readconcern.free_obj = php_phongo_readconcern_free_object; php_phongo_handler_readconcern.offset = XtOffsetOf(php_phongo_readconcern_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(readconcern); } void phongo_readconcern_init(zval* return_value, const mongoc_read_concern_t* read_concern) diff --git a/src/MongoDB/ReadPreference.c b/src/MongoDB/ReadPreference.c index cd7fed69b..110f5d922 100644 --- a/src/MongoDB/ReadPreference.c +++ b/src/MongoDB/ReadPreference.c @@ -483,13 +483,16 @@ static void php_phongo_readpreference_free_object(zend_object* object) zend_object_std_dtor(&intern->std); + if (intern->read_preference) { + mongoc_read_prefs_destroy(intern->read_preference); + } + if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } - if (intern->read_preference) { - mongoc_read_prefs_destroy(intern->read_preference); + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -516,6 +519,8 @@ static HashTable* php_phongo_readpreference_get_properties(zend_object* object) return php_phongo_readpreference_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(readpreference, Z_OBJ_READPREFERENCE) + void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS) { php_phongo_readpreference_ce = register_class_MongoDB_Driver_ReadPreference(php_phongo_serializable_ce); @@ -526,6 +531,8 @@ void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS) php_phongo_handler_readpreference.get_properties = php_phongo_readpreference_get_properties; php_phongo_handler_readpreference.free_obj = php_phongo_readpreference_free_object; php_phongo_handler_readpreference.offset = XtOffsetOf(php_phongo_readpreference_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(readpreference); } void phongo_readpreference_init(zval* return_value, const mongoc_read_prefs_t* read_prefs) diff --git a/src/MongoDB/ServerApi.c b/src/MongoDB/ServerApi.c index 844fde911..029577a6d 100644 --- a/src/MongoDB/ServerApi.c +++ b/src/MongoDB/ServerApi.c @@ -211,13 +211,16 @@ static void php_phongo_serverapi_free_object(zend_object* object) zend_object_std_dtor(&intern->std); + if (intern->server_api) { + mongoc_server_api_destroy(intern->server_api); + } + if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } - if (intern->server_api) { - mongoc_server_api_destroy(intern->server_api); + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -244,6 +247,8 @@ static HashTable* php_phongo_serverapi_get_properties(zend_object* object) return php_phongo_serverapi_get_properties_hash(object, false, true); } +PHONGO_DEFINE_PROPERTY_HANDLERS(serverapi, Z_OBJ_SERVERAPI) + void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS) { php_phongo_serverapi_ce = register_class_MongoDB_Driver_ServerApi(php_phongo_serializable_ce); @@ -254,4 +259,6 @@ void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS) php_phongo_handler_serverapi.get_properties = php_phongo_serverapi_get_properties; php_phongo_handler_serverapi.free_obj = php_phongo_serverapi_free_object; php_phongo_handler_serverapi.offset = XtOffsetOf(php_phongo_serverapi_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(serverapi); } diff --git a/src/MongoDB/ServerDescription.c b/src/MongoDB/ServerDescription.c index 7a21e9e07..faf29a7a7 100644 --- a/src/MongoDB/ServerDescription.c +++ b/src/MongoDB/ServerDescription.c @@ -158,13 +158,16 @@ static void php_phongo_serverdescription_free_object(zend_object* object) zend_object_std_dtor(&intern->std); + if (intern->server_description) { + mongoc_server_description_destroy(intern->server_description); + } + if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } - if (intern->server_description) { - mongoc_server_description_destroy(intern->server_description); + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -267,6 +270,8 @@ static HashTable* php_phongo_serverdescription_get_properties(zend_object* objec return php_phongo_serverdescription_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(serverdescription, Z_OBJ_SERVERDESCRIPTION); + void php_phongo_serverdescription_init_ce(INIT_FUNC_ARGS) { php_phongo_serverdescription_ce = register_class_MongoDB_Driver_ServerDescription(); @@ -277,6 +282,8 @@ void php_phongo_serverdescription_init_ce(INIT_FUNC_ARGS) php_phongo_handler_serverdescription.get_properties = php_phongo_serverdescription_get_properties; php_phongo_handler_serverdescription.free_obj = php_phongo_serverdescription_free_object; php_phongo_handler_serverdescription.offset = XtOffsetOf(php_phongo_serverdescription_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(serverdescription); } void phongo_serverdescription_init_ex(zval* return_value, mongoc_server_description_t* server_description, bool copy) diff --git a/src/MongoDB/TopologyDescription.c b/src/MongoDB/TopologyDescription.c index ab625dff0..733ad3709 100644 --- a/src/MongoDB/TopologyDescription.c +++ b/src/MongoDB/TopologyDescription.c @@ -107,13 +107,16 @@ static void php_phongo_topologydescription_free_object(zend_object* object) zend_object_std_dtor(&intern->std); + if (intern->topology_description) { + mongoc_topology_description_destroy(intern->topology_description); + } + if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } - if (intern->topology_description) { - mongoc_topology_description_destroy(intern->topology_description); + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -180,6 +183,8 @@ static HashTable* php_phongo_topologydescription_get_properties(zend_object* obj return php_phongo_topologydescription_get_properties_hash(object, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(topologydescription, Z_OBJ_TOPOLOGYDESCRIPTION) + void php_phongo_topologydescription_init_ce(INIT_FUNC_ARGS) { php_phongo_topologydescription_ce = register_class_MongoDB_Driver_TopologyDescription(); @@ -190,6 +195,8 @@ void php_phongo_topologydescription_init_ce(INIT_FUNC_ARGS) php_phongo_handler_topologydescription.get_properties = php_phongo_topologydescription_get_properties; php_phongo_handler_topologydescription.free_obj = php_phongo_topologydescription_free_object; php_phongo_handler_topologydescription.offset = XtOffsetOf(php_phongo_topologydescription_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(topologydescription); } void phongo_topologydescription_init(zval* return_value, mongoc_topology_description_t* topology_description) diff --git a/src/MongoDB/WriteConcern.c b/src/MongoDB/WriteConcern.c index c0edb5a05..2f1f7aef8 100644 --- a/src/MongoDB/WriteConcern.c +++ b/src/MongoDB/WriteConcern.c @@ -368,13 +368,16 @@ static void php_phongo_writeconcern_free_object(zend_object* object) zend_object_std_dtor(&intern->std); + if (intern->write_concern) { + mongoc_write_concern_destroy(intern->write_concern); + } + if (intern->properties) { - zend_hash_destroy(intern->properties); - FREE_HASHTABLE(intern->properties); + zend_hash_release(intern->properties); } - if (intern->write_concern) { - mongoc_write_concern_destroy(intern->write_concern); + if (intern->php_properties) { + zend_hash_release(intern->php_properties); } } @@ -401,6 +404,8 @@ static HashTable* php_phongo_writeconcern_get_properties(zend_object* object) return php_phongo_writeconcern_get_properties_hash(object, false, false, false); } +PHONGO_DEFINE_PROPERTY_HANDLERS(writeconcern, Z_OBJ_WRITECONCERN) + void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS) { php_phongo_writeconcern_ce = register_class_MongoDB_Driver_WriteConcern(php_phongo_serializable_ce); @@ -411,6 +416,8 @@ void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS) php_phongo_handler_writeconcern.get_properties = php_phongo_writeconcern_get_properties; php_phongo_handler_writeconcern.free_obj = php_phongo_writeconcern_free_object; php_phongo_handler_writeconcern.offset = XtOffsetOf(php_phongo_writeconcern_t, std); + + PHONGO_ASSIGN_PROPERTY_HANDLERS(writeconcern); } void phongo_writeconcern_init(zval* return_value, const mongoc_write_concern_t* write_concern) diff --git a/src/phongo_compat.h b/src/phongo_compat.h index 5b4f01816..f1f1e3fd0 100644 --- a/src/phongo_compat.h +++ b/src/phongo_compat.h @@ -99,9 +99,7 @@ #define PHONGO_RETVAL_SMART_STR(val) RETVAL_STRINGL(ZSTR_VAL((val).s), ZSTR_LEN((val).s)); #define ZVAL_STATIC_INIT \ { \ - { \ - 0 \ - } \ + { 0 } \ } #define ADD_NEXT_INDEX_INT64_OBJ(_zv, _value) \ diff --git a/src/phongo_structs.h b/src/phongo_structs.h index 2fc3c3ae2..d25184db8 100644 --- a/src/phongo_structs.h +++ b/src/phongo_structs.h @@ -122,12 +122,14 @@ typedef struct { typedef struct { mongoc_read_concern_t* read_concern; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_readconcern_t; typedef struct { mongoc_read_prefs_t* read_preference; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_readpreference_t; @@ -141,12 +143,14 @@ typedef struct { typedef struct { mongoc_server_api_t* server_api; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_serverapi_t; typedef struct { mongoc_server_description_t* server_description; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_serverdescription_t; @@ -160,12 +164,14 @@ typedef struct { typedef struct { mongoc_topology_description_t* topology_description; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_topologydescription_t; typedef struct { - HashTable* properties; mongoc_write_concern_t* write_concern; + HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_writeconcern_t; @@ -197,12 +203,14 @@ typedef struct { size_t data_len; uint8_t type; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_binary_t; typedef struct { bson_t* bson; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_packedarray_t; @@ -220,6 +228,7 @@ typedef struct { size_t key; zval current; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_iterator_t; @@ -228,6 +237,7 @@ typedef struct { size_t ref_len; char id[25]; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_dbpointer_t; @@ -235,6 +245,7 @@ typedef struct { bool initialized; bson_decimal128_t decimal; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_decimal128_t; @@ -242,6 +253,7 @@ typedef struct { bool initialized; int64_t integer; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_int64_t; @@ -250,6 +262,7 @@ typedef struct { size_t code_len; bson_t* scope; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_javascript_t; @@ -265,6 +278,7 @@ typedef struct { bool initialized; char oid[25]; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_objectid_t; @@ -274,6 +288,7 @@ typedef struct { char* flags; int flags_len; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_regex_t; @@ -281,6 +296,7 @@ typedef struct { char* symbol; size_t symbol_len; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_symbol_t; @@ -289,6 +305,7 @@ typedef struct { uint32_t increment; uint32_t timestamp; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_timestamp_t; @@ -300,6 +317,7 @@ typedef struct { bool initialized; int64_t milliseconds; HashTable* properties; + HashTable* php_properties; zend_object std; } php_phongo_utcdatetime_t; diff --git a/tests/bson/bug1598-002.phpt b/tests/bson/bug1598-002.phpt index de32da9a8..0b675f37a 100644 --- a/tests/bson/bug1598-002.phpt +++ b/tests/bson/bug1598-002.phpt @@ -1,8 +1,5 @@ --TEST-- PHPC-1598: BSON type get_gc should delegate to zend_std_get_properties ---SKIPIF-- - -=', '8.1.99'); ?> --FILE-- new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], + [ 'dbpointer' => createDBPointer() ], + [ 'decimal128' => new MongoDB\BSON\Decimal128('1234.5678') ], + [ 'int64' => new MongoDB\BSON\Int64('9223372036854775807') ], + // JavaScript w/ scope may not be necessary (same code path as w/o scope), but we'll test it anyway + [ 'javascript' => new MongoDB\BSON\Javascript('function() { return 1; }') ], + + // The context is recreated every time with a different object ID + //[ 'javascript_ws' => new MongoDB\BSON\Javascript('function() { return a; }', ['a' => 1]) ], + + // MaxKey and MinKey don't have get_properties or get_gc handlers, but we'll test them anyway + [ 'maxkey' => new MongoDB\BSON\MaxKey ], + [ 'minkey' => new MongoDB\BSON\MinKey ], + [ 'objectid' => new MongoDB\BSON\ObjectId ], + [ 'regex' => new MongoDB\BSON\Regex('pattern', 'i') ], + [ 'symbol' => createSymbol() ], + [ 'timestamp' => new MongoDB\BSON\Timestamp(1234, 5678) ], + [ 'utcdatetime' => new MongoDB\BSON\UTCDateTime ], +]; + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf1 = ob_get_clean(); +if ($buf1 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +gc_enable(); +gc_collect_cycles(); + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf2 = ob_get_clean(); +if ($buf2 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +if ($buf1 === $buf2) { + echo "OK!\n"; + exit(0); +} else { + echo("buf1 != buf2: $buf1\n\n IS NOT EQUAL TO \n\n$buf2\n"); + exit(1); +} + +?> +--EXPECT-- +OK! diff --git a/tests/bson/bug2505-002.phpt b/tests/bson/bug2505-002.phpt new file mode 100644 index 000000000..b493dd725 --- /dev/null +++ b/tests/bson/bug2505-002.phpt @@ -0,0 +1,69 @@ +-TEST-- +PHPC-2505: Setting and unsetting a property may interfere with using foreach to iterate objects +--FILE-- + new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], + [ 'dbpointer' => createDBPointer() ], + [ 'decimal128' => new MongoDB\BSON\Decimal128('1234.5678') ], + [ 'int64' => new MongoDB\BSON\Int64('9223372036854775807') ], + // JavaScript w/ scope may not be necessary (same code path as w/o scope), but we'll test it anyway + [ 'javascript' => new MongoDB\BSON\Javascript('function() { return 1; }') ], + // The context is recreated every time with a different object ID + //[ 'javascript_ws' => new MongoDB\BSON\Javascript('function() { return a; }', ['a' => 1]) ], + // MaxKey and MinKey don't have get_properties or get_gc handlers, but we'll test them anyway + [ 'maxkey' => new MongoDB\BSON\MaxKey ], + [ 'minkey' => new MongoDB\BSON\MinKey ], + [ 'objectid' => new MongoDB\BSON\ObjectId ], + [ 'regex' => new MongoDB\BSON\Regex('pattern', 'i') ], + [ 'symbol' => createSymbol() ], + [ 'timestamp' => new MongoDB\BSON\Timestamp(1234, 5678) ], + [ 'utcdatetime' => new MongoDB\BSON\UTCDateTime ], +]; + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf1 = ob_get_clean(); +if ($buf1 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +foreach ($tests as $test) { + $test = reset($test); + $test->a = 'test'; + unset($test->a); +} + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf2 = ob_get_clean(); +if ($buf2 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +if ($buf1 === $buf2) { + echo "OK!\n"; + exit(0); +} else { + echo("buf1 != buf2: $buf1\n!=\n$buf2\n"); +} + +?> +--EXPECT-- +OK! diff --git a/tests/bson/bug2505-003.phpt b/tests/bson/bug2505-003.phpt new file mode 100644 index 000000000..841662391 --- /dev/null +++ b/tests/bson/bug2505-003.phpt @@ -0,0 +1,70 @@ +--TEST-- +PHPC-2505: Setting and unsetting a property may interfere with using foreach to iterate objects +--FILE-- + new MongoDB\BSON\Binary('foo', MongoDB\BSON\Binary::TYPE_GENERIC) ], + [ 'dbpointer' => createDBPointer() ], + [ 'decimal128' => new MongoDB\BSON\Decimal128('1234.5678') ], + [ 'int64' => new MongoDB\BSON\Int64('9223372036854775807') ], + // JavaScript w/ scope may not be necessary (same code path as w/o scope), but we'll test it anyway + [ 'javascript' => new MongoDB\BSON\Javascript('function() { return 1; }') ], + // The context is recreated every time with a different object ID + //[ 'javascript_ws' => new MongoDB\BSON\Javascript('function() { return a; }', ['a' => 1]) ], + // MaxKey and MinKey don't have get_properties or get_gc handlers, but we'll test them anyway + [ 'maxkey' => new MongoDB\BSON\MaxKey ], + [ 'minkey' => new MongoDB\BSON\MinKey ], + [ 'objectid' => new MongoDB\BSON\ObjectId ], + [ 'regex' => new MongoDB\BSON\Regex('pattern', 'i') ], + [ 'symbol' => createSymbol() ], + [ 'timestamp' => new MongoDB\BSON\Timestamp(1234, 5678) ], + [ 'utcdatetime' => new MongoDB\BSON\UTCDateTime ], +]; + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf1 = ob_get_clean(); +if ($buf1 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +foreach ($tests as $test) { + $test = reset($test); + $t = &$test->a; + $t = 'test'; + unset($test->a, $t); +} + +ob_start(); +foreach ($tests as $test) { + echo key($test), "\n"; + $test = reset($test); + + foreach ($test as $k => $v) { + var_dump($k, $v); + } +} +$buf2 = ob_get_clean(); +if ($buf2 === false) { + throw new \AssertionError("Could not flush buffer"); +} + +if ($buf1 === $buf2) { + echo "OK!\n"; + exit(0); +} else { + echo("buf1 != buf2: $buf1\n!=\n$buf2\n"); +} + +?> +--EXPECT-- +OK! diff --git a/tests/readConcern/bug1598-002.phpt b/tests/readConcern/bug1598-002.phpt index fb7450f7c..a343f81de 100644 --- a/tests/readConcern/bug1598-002.phpt +++ b/tests/readConcern/bug1598-002.phpt @@ -1,8 +1,5 @@ --TEST-- PHPC-1598: ReadConcern get_gc should delegate to zend_std_get_properties ---SKIPIF-- - -=', '8.1.99'); ?> --FILE-- -=', '8.1.99'); ?> --FILE-- -=', '8.1.99'); ?> --FILE--