Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ PHP 8.7 INTERNALS UPGRADE NOTES
- Added a new zend_object_copy() function which increases the refcount of
a zend_object* and returns it. Allowing more descriptive code rather than
doing an assignment followed by GC_ADDREF().
- Added zend_call_method_if_exists_ex() which accepts named parameters and
retrieving the callability failure error message.

========================
2. Build system changes
Expand Down
21 changes: 15 additions & 6 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,12 +913,21 @@ static zend_always_inline void zend_call_known_instance_method_with_1_params(
ZEND_API void zend_call_known_instance_method_with_2_params(
zend_function *fn, zend_object *this_ptr, zval *retval_ptr, zval *param1, zval *param2);

/* Call method if it exists. Return FAILURE if method does not exist or call failed.
* If FAILURE is returned, retval will be UNDEF. As such, destroying retval unconditionally
* is legal. */
ZEND_API zend_result zend_call_method_if_exists(
zend_object *this_ptr, zend_string *method_name, zval *retval,
uint32_t param_count, zval *params);
/* Call method if it exists.
* Return FAILURE if method does not exist.
* If FAILURE is returned, retval will be UNDEF, and error will contain the validation failure message if provided.
* As such, destroying retval unconditionally is legal.
*/
ZEND_API zend_result zend_call_method_if_exists_ex(
zend_object *this_ptr, zend_string *method_name, zval *retval_ptr,
uint32_t param_count, zval *params, HashTable *named_params, char **error);

static zend_always_inline zend_result zend_call_method_if_exists(
zend_object *this_ptr, zend_string *method_name,
zval *retval_ptr, uint32_t param_count, zval *params
) {
return zend_call_method_if_exists_ex(this_ptr, method_name, retval_ptr, param_count, params, NULL, NULL);
}

ZEND_API zend_result zend_delete_global_variable(zend_string *name);

Expand Down
14 changes: 7 additions & 7 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -1184,21 +1184,21 @@ ZEND_API void zend_call_known_instance_method_with_2_params(
zend_call_known_instance_method(fn, this_ptr, retval_ptr, 2, params);
}

ZEND_API zend_result zend_call_method_if_exists(
zend_object *this_ptr, zend_string *method_name, zval *retval,
uint32_t param_count, zval *params)
{
ZEND_API zend_result zend_call_method_if_exists_ex(
zend_object *this_ptr, zend_string *method_name, zval *retval_ptr,
uint32_t param_count, zval *params, HashTable *named_params, char **error
) {
zval zval_method;
zend_fcall_info_cache fcc;

ZVAL_STR(&zval_method, method_name);

if (UNEXPECTED(!zend_is_callable_ex(&zval_method, this_ptr, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL))) {
ZVAL_UNDEF(retval);
if (UNEXPECTED(!zend_is_callable_ex(&zval_method, this_ptr, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, error))) {
ZVAL_UNDEF(retval_ptr);
return FAILURE;
}

zend_call_known_fcc(&fcc, retval, param_count, params, NULL);
zend_call_known_fcc(&fcc, retval_ptr, param_count, params, named_params);
/* Need to free potential trampoline (__call/__callStatic) copied function handler before releasing the closure */
zend_release_fcall_info_cache(&fcc);
return SUCCESS;
Expand Down
Loading