Skip to content

PHPC-1849: Handle deprecation of Serializable in PHP 8.1 #1246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Sep 1, 2021

Conversation

jmikola
Copy link
Member

@jmikola jmikola commented Aug 10, 2021

@jmikola jmikola force-pushed the phpc-1849 branch 2 times, most recently from 86ae7c3 to b3d1920 Compare August 17, 2021 16:58
jmikola added 13 commits August 17, 2021 16:48
These methods will be used on PHP 7.4+ when available. Implementing them is required to suppress a deprecation notice on PHP 8.1+.

This commit also renames is_debug parameter for get_properties_hash utility functions (and related macros) to more accurately reflect its purpose of allocating a new HashTable instead of using an internal props table.
@jmikola jmikola marked this pull request as ready for review August 18, 2021 13:35
@jmikola jmikola requested review from alcaeus and tanlisu August 18, 2021 13:35
Copy link
Member

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good, just a couple of questions on the code to judge potential refactoring effort.

Comment on lines +85 to +93
{
zval data, type;

ZVAL_STRINGL(&data, intern->data, intern->data_len);
zend_hash_str_update(props, "data", sizeof("data") - 1, &data);

ZVAL_LONG(&type, intern->type);
zend_hash_str_update(props, "type", sizeof("type") - 1, &type);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've wondered about this before. What's the practical reason for nesting? Is it to only conditionally allocate the two zval structs on the stack and avoid doing so if there's no data to handle?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These aren't even conditionally allocated. We're just using braces to create a scope and allow us to declare variables inline. Our C compiler options would otherwise flag this as a warning and require that we declare these at the top of the function scope.

Comment on lines +332 to +334
ZEND_BEGIN_ARG_INFO_EX(ai_Binary___unserialize, 0, 0, 1)
ZEND_ARG_ARRAY_INFO(0, data, 0)
ZEND_END_ARG_INFO()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wondering about this for a while as well: shouldn't this be in PHP's realm to provide arginfo structs for its own interface? We're duplicating this in a lot of our classes, where using ai_Serializable___unserialize would work just fine everywhere else 🤔

// cc @nikic

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting point, although I could see this being problematic if PHP happened to change its arginfo between versions. I think this may relate to why interfaces in 8.1 started using tentative return types, to defer the actual changes to PHP 9.0.

Allowing extensions to define their own arginfo presumably lets us use a narrower API if we want, which would still conform with the interface in core.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nowadays we auto-generate all arginfo (as well as class declarations in general) anyway, so we don't have any particular interest in making reuse simpler.

Comment on lines +87 to +90
ZVAL_STRING(&ref, intern->ref);
ZVAL_STRING(&id, intern->id);
zend_hash_str_update(props, "ref", sizeof("ref") - 1, &ref);
zend_hash_str_update(props, "id", sizeof("id") - 1, &id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to change anything here, but getting to the second class in the code review I thought "I suppose this is now 20 times the same change", and I immediately catch the different code organisation between this and the Binary class up there. No need to change since I'd like to refactor this code in general: macros that call the combination of ZVAL_* and zend_hash_str_update would help since they could handle the scoping (if it's necessary, see earlier comment).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created PHPC-1962 to track this.

Comment on lines +224 to +235
/* {{{ proto void MongoDB\Driver\DBPointer::__unserialize(array $data)
*/
static PHP_METHOD(DBPointer, __unserialize)
{
zval* data;

PHONGO_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(data)
PHONGO_PARSE_PARAMETERS_END();

php_phongo_dbpointer_init_from_hash(Z_DBPOINTER_OBJ_P(getThis()), Z_ARRVAL_P(data));
} /* }}} */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is another one where I feel PHP could offer a macro:

/* {{{ proto void MongoDB\Driver\DBPointer::__unserialize(array $data)
*/
IMPL_SERIALIZABLE___UNSERIALIZE_START()
	php_phongo_dbpointer_init_from_hash(Z_DBPOINTER_OBJ_P(getThis()), Z_ARRVAL_P(data));
IMPL_SERIALIZABLE___UNSERIALIZE_END() /* }}} */

Since the other logic is always the same, this may be an improvement to help reducing the menial task of adding this to multiple classes...


echo throws(function() {
unserialize('O:19:"MongoDB\BSON\Binary":1:{s:4:"data";s:6:"foobar";}');
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know many of these files don't do this yet, but we should be using the ::class constant. No need to change this in these files as they're most likely copypasta from the originals, so I'll see if I can do a nice find/replace to take care of these.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would likely require a sprintf since we'd also need to capture the string length in the preceding integer. I'll leave this to you to make a ticket if you'd like to track the work.

@jmikola
Copy link
Member Author

jmikola commented Aug 31, 2021

Noted one test failure on AppVeyor for 32-bit CursorId var_dump() output. Fixed in the most recent push and will wait for green CI before merging.

@jmikola jmikola merged commit bd10948 into mongodb:master Sep 1, 2021
@jmikola jmikola deleted the phpc-1849 branch September 1, 2021 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants