@@ -1226,6 +1226,77 @@ int zephir_create_closure_ex(zval *return_value, zval *this_ptr, zend_class_entr
1226
1226
return SUCCESS ;
1227
1227
}
1228
1228
1229
+ /**
1230
+ * Copied from php-src source tree for PHP 8.4
1231
+ */
1232
+ #ifndef object_init_with_constructor
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
+
1229
1300
/**
1230
1301
* Creates a new instance dynamically. Call constructor without parameters
1231
1302
*/
@@ -1244,38 +1315,7 @@ int zephir_create_instance(zval *return_value, const zval *class_name)
1244
1315
return FAILURE ;
1245
1316
}
1246
1317
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 );
1279
1319
}
1280
1320
1281
1321
/**
@@ -1301,40 +1341,5 @@ int zephir_create_instance_params(zval *return_value, const zval *class_name, zv
1301
1341
return FAILURE ;
1302
1342
}
1303
1343
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 ));
1340
1345
}
0 commit comments