@@ -1226,6 +1226,77 @@ int zephir_create_closure_ex(zval *return_value, zval *this_ptr, zend_class_entr
12261226 return SUCCESS ;
12271227}
12281228
1229+ /**
1230+ * Copied from php-src source tree for PHP 8.4
1231+ */
1232+ #if PHP_VERSION_ID < 80400
1233+ static zend_result object_init_with_constructor (zval * arg , zend_class_entry * class_type , uint32_t param_count , zval * params , HashTable * named_params )
1234+ {
1235+ zend_result status = object_and_properties_init (arg , class_type , NULL );
1236+ if (UNEXPECTED (status == FAILURE )) {
1237+ ZVAL_UNDEF (arg );
1238+ return FAILURE ;
1239+ }
1240+ zend_object * obj = Z_OBJ_P (arg );
1241+ zend_function * constructor = obj -> handlers -> get_constructor (obj );
1242+ if (constructor == NULL ) {
1243+ /* The constructor can be NULL for 2 different reasons:
1244+ * - It is not defined
1245+ * - We are not allowed to call the constructor (e.g. private, or internal opaque class)
1246+ * and an exception has been thrown
1247+ * in the former case, we are (mostly) done and the object is initialized,
1248+ * in the latter we need to destroy the object as initialization failed
1249+ */
1250+ if (UNEXPECTED (EG (exception ))) {
1251+ zval_ptr_dtor (arg );
1252+ ZVAL_UNDEF (arg );
1253+ return FAILURE ;
1254+ }
1255+
1256+ /* Surprisingly, this is the only case where internal classes will allow to pass extra arguments
1257+ * However, if there are named arguments (and it is not empty),
1258+ * an Error must be thrown to be consistent with new ClassName() */
1259+ if (UNEXPECTED (named_params != NULL && zend_hash_num_elements (named_params ) != 0 )) {
1260+ /* Throw standard Error */
1261+ zend_string * arg_name = NULL ;
1262+ zend_hash_get_current_key (named_params , & arg_name , /* num_index */ NULL );
1263+ ZEND_ASSERT (arg_name != NULL );
1264+ zend_throw_error (NULL , "Unknown named parameter $%s" , ZSTR_VAL (arg_name ));
1265+ /* Do not call destructor, free object, and set arg to IS_UNDEF */
1266+ zend_object_store_ctor_failed (obj );
1267+ zval_ptr_dtor (arg );
1268+ ZVAL_UNDEF (arg );
1269+ return FAILURE ;
1270+ } else {
1271+ return SUCCESS ;
1272+ }
1273+ }
1274+ /* A constructor should not return a value, however if an exception is thrown
1275+ * zend_call_known_function() will set the retval to IS_UNDEF */
1276+ zval retval ;
1277+ zend_call_known_function (
1278+ constructor ,
1279+ obj ,
1280+ class_type ,
1281+ & retval ,
1282+ param_count ,
1283+ params ,
1284+ named_params
1285+ );
1286+ if (Z_TYPE (retval ) == IS_UNDEF ) {
1287+ /* Do not call destructor, free object, and set arg to IS_UNDEF */
1288+ zend_object_store_ctor_failed (obj );
1289+ zval_ptr_dtor (arg );
1290+ ZVAL_UNDEF (arg );
1291+ return FAILURE ;
1292+ } else {
1293+ /* Unlikely, but user constructors may return any value they want */
1294+ zval_ptr_dtor (& retval );
1295+ return SUCCESS ;
1296+ }
1297+ }
1298+ #endif
1299+
12291300/**
12301301 * Creates a new instance dynamically. Call constructor without parameters
12311302 */
@@ -1244,38 +1315,7 @@ int zephir_create_instance(zval *return_value, const zval *class_name)
12441315 return FAILURE ;
12451316 }
12461317
1247- if (UNEXPECTED (object_init_ex (return_value , ce ) != SUCCESS )) {
1248- return FAILURE ;
1249- }
1250-
1251- if (EXPECTED (Z_OBJ_HT_P (return_value )-> get_constructor )) {
1252- zend_object * obj = Z_OBJ_P (return_value );
1253- zend_function * ctor = Z_OBJ_HT_P (return_value )-> get_constructor (obj );
1254- if (ctor ) {
1255- zend_fcall_info fci ;
1256- zend_fcall_info_cache fcc ;
1257-
1258- zend_class_entry * ce = Z_OBJCE_P (return_value );
1259-
1260- fci .size = sizeof (fci );
1261- fci .object = obj ;
1262- fci .retval = 0 ;
1263- fci .param_count = 0 ;
1264- fci .params = 0 ;
1265- fci .named_params = NULL ;
1266-
1267- ZVAL_NULL (& fci .function_name );
1268-
1269- fcc .object = obj ;
1270- fcc .called_scope = ce ;
1271- fcc .calling_scope = ce ;
1272- fcc .function_handler = ctor ;
1273-
1274- return zend_fcall_info_call (& fci , & fcc , NULL , NULL );
1275- }
1276- }
1277-
1278- return SUCCESS ;
1318+ return object_init_with_constructor (return_value , ce , 0 , NULL , NULL );
12791319}
12801320
12811321/**
@@ -1301,40 +1341,5 @@ int zephir_create_instance_params(zval *return_value, const zval *class_name, zv
13011341 return FAILURE ;
13021342 }
13031343
1304- if (UNEXPECTED (object_init_ex (return_value , ce ) != SUCCESS )) {
1305- return FAILURE ;
1306- }
1307-
1308- if (EXPECTED (Z_OBJ_HT_P (return_value )-> get_constructor )) {
1309- zend_object * obj = Z_OBJ_P (return_value );
1310- zend_function * ctor = Z_OBJ_HT_P (return_value )-> get_constructor (obj );
1311- if (ctor ) {
1312- int status ;
1313- zend_fcall_info fci ;
1314- zend_fcall_info_cache fcc ;
1315-
1316- zend_class_entry * ce = Z_OBJCE_P (return_value );
1317-
1318- fci .size = sizeof (fci );
1319- fci .object = obj ;
1320- fci .retval = 0 ;
1321- fci .param_count = 0 ;
1322- fci .params = 0 ;
1323- fci .named_params = NULL ;
1324-
1325- ZVAL_NULL (& fci .function_name );
1326-
1327- fcc .object = obj ;
1328- fcc .called_scope = ce ;
1329- fcc .calling_scope = ce ;
1330- fcc .function_handler = ctor ;
1331-
1332- zend_fcall_info_args_ex (& fci , fcc .function_handler , params );
1333- status = zend_fcall_info_call (& fci , & fcc , NULL , NULL );
1334- zend_fcall_info_args_clear (& fci , 1 );
1335- return status ;
1336- }
1337- }
1338-
1339- return SUCCESS ;
1344+ return object_init_with_constructor (return_value , ce , 0 , NULL , Z_ARRVAL_P (params ));
13401345}
0 commit comments