Skip to content

Commit af1e289

Browse files
committed
ext/json: Refactor php_json_encode_serializable_object() to call method directly
1 parent 75a15cf commit af1e289

File tree

2 files changed

+16
-29
lines changed

2 files changed

+16
-29
lines changed

UPGRADING.INTERNALS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ PHP 8.5 INTERNALS UPGRADE NOTES
2626
. The gdImageScale*() and gdImageRotate*() helpers are now internal in the
2727
bundled libgd, like they have been in external libgd as of gd-2.1.1.
2828

29+
- ext/json
30+
. php_json_encode_serializable_object() now assumes `EG(active)`,
31+
if not a bailout is caused. Therefore a minor BC break exists if the
32+
`PHP_JSON_PARTIAL_OUTPUT_ON_ERROR` option is in use.
33+
However, this situation is highly unlikely.
34+
2935
- ext/libxml
3036
. The refcount APIs now return an `unsigned int` instead of an `int`.
3137

ext/json/json_encoder.c

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,11 @@ zend_result php_json_escape_string(
579579
}
580580
/* }}} */
581581

582-
static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
582+
static zend_result php_json_encode_serializable_object(smart_str *buf, zend_object *obj, int options, php_json_encoder *encoder)
583583
{
584-
zend_class_entry *ce = Z_OBJCE_P(val);
585-
zend_object *obj = Z_OBJ_P(val);
584+
zend_class_entry *ce = obj->ce;
586585
uint32_t *guard = zend_get_recursion_guard(obj);
587-
zval retval, fname;
586+
zval retval;
588587
zend_result return_code;
589588

590589
ZEND_ASSERT(guard != NULL);
@@ -599,35 +598,19 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
599598

600599
ZEND_GUARD_PROTECT_RECURSION(guard, JSON);
601600

602-
ZVAL_STRING(&fname, "jsonSerialize");
603-
604-
if (FAILURE == call_user_function(NULL, val, &fname, &retval, 0, NULL) || Z_TYPE(retval) == IS_UNDEF) {
605-
if (!EG(exception)) {
606-
zend_throw_exception_ex(NULL, 0, "Failed calling %s::jsonSerialize()", ZSTR_VAL(ce->name));
607-
}
608-
zval_ptr_dtor(&fname);
609-
601+
zend_function *json_serialize_method = zend_hash_str_find_ptr(&ce->function_table, ZEND_STRL("jsonserialize"));
602+
ZEND_ASSERT(json_serialize_method != NULL && "This should be guaranteed prior to calling this function");
603+
zend_call_known_function(json_serialize_method, obj, ce, &retval, 0, NULL, NULL);
604+
/* An exception has occurred */
605+
if (Z_TYPE(retval) == IS_UNDEF) {
610606
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
611607
smart_str_appendl(buf, "null", 4);
612608
}
613609
ZEND_GUARD_UNPROTECT_RECURSION(guard, JSON);
614610
return FAILURE;
615611
}
616612

617-
if (EG(exception)) {
618-
/* Error already raised */
619-
zval_ptr_dtor(&retval);
620-
zval_ptr_dtor(&fname);
621-
622-
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
623-
smart_str_appendl(buf, "null", 4);
624-
}
625-
ZEND_GUARD_UNPROTECT_RECURSION(guard, JSON);
626-
return FAILURE;
627-
}
628-
629-
if ((Z_TYPE(retval) == IS_OBJECT) &&
630-
(Z_OBJ(retval) == Z_OBJ_P(val))) {
613+
if (Z_TYPE(retval) == IS_OBJECT && Z_OBJ(retval) == obj) {
631614
/* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
632615
ZEND_GUARD_UNPROTECT_RECURSION(guard, JSON);
633616
return_code = php_json_encode_array(buf, &retval, options, encoder);
@@ -638,11 +621,9 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
638621
}
639622

640623
zval_ptr_dtor(&retval);
641-
zval_ptr_dtor(&fname);
642624

643625
return return_code;
644626
}
645-
/* }}} */
646627

647628
static zend_result php_json_encode_serializable_enum(smart_str *buf, zval *val, int options, php_json_encoder *encoder)
648629
{
@@ -691,7 +672,7 @@ zend_result php_json_encode_zval(smart_str *buf, zval *val, int options, php_jso
691672

692673
case IS_OBJECT:
693674
if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce)) {
694-
return php_json_encode_serializable_object(buf, val, options, encoder);
675+
return php_json_encode_serializable_object(buf, Z_OBJ_P(val), options, encoder);
695676
}
696677
if (Z_OBJCE_P(val)->ce_flags & ZEND_ACC_ENUM) {
697678
return php_json_encode_serializable_enum(buf, val, options, encoder);

0 commit comments

Comments
 (0)