Skip to content

Commit f232a33

Browse files
committed
PHP-8.0 support
1 parent 26cbf1e commit f232a33

File tree

10 files changed

+179
-53
lines changed

10 files changed

+179
-53
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ php:
1111
- 7.1
1212
- 7.2
1313
- 7.3
14-
- nightly # doesn't work yet on PHP 7.4! not building.
14+
- 7.4
15+
- 8.0
16+
- nightly
1517

1618

1719
# setting the env is the easiest, because it will mix with all the separate php versions (travis does this)

zend/callable.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@ void Callable::invoke(INTERNAL_FUNCTION_PARAMETERS)
3636
#else
3737
// Sanity check
3838
assert(info[argc].type != 0 && info[argc].name == nullptr);
39-
4039
// the callable we are retrieving
40+
#if PHP_VERSION_ID < 80000
4141
Callable *callable = reinterpret_cast<Callable*>(info[argc].type);
42+
#else
43+
Callable *callable = reinterpret_cast<Callable*>(info[argc].type.ptr);
44+
#endif
4245
#endif
4346

4447
// check if sufficient parameters were passed (for some reason this check
@@ -99,10 +102,10 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
99102
_argv[_argc + 1].class_name = reinterpret_cast<const char*>(this);
100103
#else
101104
// @todo this is broken. the zend engine, from 7.2 onwards copies over
102-
// the struct and slices of the last element, because the num_args
105+
// the struct and slices off the last element, because the num_args
103106
// is incorrect in their view. another place to put this may be
104107
// hiding it behind the fname
105-
_argv[_argc + 1].type = reinterpret_cast<zend_type>(this);
108+
// _argv[_argc + 1].type = reinterpret_cast<zend_type>(this);
106109
#endif
107110

108111
// we use our own invoke method, which does a lookup
@@ -129,8 +132,10 @@ void Callable::initialize(zend_internal_function_info *info, const char *classna
129132
{
130133
// initialize all common elements
131134
info->required_num_args = _required;
135+
#if PHP_VERSION_ID < 80000
132136
info->return_reference = false;
133137
info->_is_variadic = false;
138+
#endif
134139

135140
// the structure has been slightly altered since php7.2
136141
#if PHP_VERSION_ID < 70200
@@ -147,10 +152,12 @@ void Callable::initialize(zend_internal_function_info *info, const char *classna
147152
#else
148153
// the properties that are available on php 7.2 and higher
149154
info->required_num_args = _required;
155+
#if PHP_VERSION_ID < 80000
150156
info->return_reference = false;
151157
info->_is_variadic = false;
152158
info->type = ZEND_TYPE_ENCODE((int)_return, true);
153159
#endif
160+
#endif
154161
}
155162

156163
/**

zend/callable.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ class Callable
5353

5454
// initialize all elements to null
5555
_argv[i].name = nullptr;
56+
#if PHP_VERSION_ID < 80000
5657
_argv[i].is_variadic = false;
5758
_argv[i].pass_by_reference = false;
58-
59+
#endif
5960
// initialize the extra argument prior to 7.2
6061
#if PHP_VERSION_ID < 70200
6162
_argv[i].class_name = nullptr;
62-
#else
63+
#elif PHP_VERSION_ID < 80000
6364
_argv[i].type = 0;
6465
#endif
6566
}
@@ -198,6 +199,23 @@ class Callable
198199
case Type::Object: info->type_hint = IS_OBJECT; break; // must be an object of the given classname
199200
case Type::Callable: info->type_hint = IS_CALLABLE; break; // anything that can be invoked
200201
default: info->type_hint = IS_UNDEF; break; // if not specified we allow anything
202+
#elif PHP_VERSION_ID >= 80000
203+
case Type::Undefined: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_UNDEF, arg.allowNull(), 0); break; // undefined means we'll accept any type
204+
case Type::Null: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_UNDEF, arg.allowNull(), 0); break; // this is likely an error, what good would accepting NULL be? accept anything
205+
case Type::False: info->type = (zend_type) ZEND_TYPE_INIT_CODE(_IS_BOOL, arg.allowNull(), 0); break; // accept true as well ;)
206+
case Type::True: info->type = (zend_type) ZEND_TYPE_INIT_CODE(_IS_BOOL, arg.allowNull(), 0); break; // accept false as well
207+
case Type::Bool: info->type = (zend_type) ZEND_TYPE_INIT_CODE(_IS_BOOL, arg.allowNull(), 0); break; // any bool will do, true, false, the options are limitless
208+
case Type::Numeric: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_LONG, arg.allowNull(), 0); break; // accept integers here
209+
case Type::Float: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_DOUBLE, arg.allowNull(), 0); break; // floating-point values welcome too
210+
case Type::String: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_STRING, arg.allowNull(), 0); break; // accept strings, should auto-cast objects with __toString as well
211+
case Type::Array: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_ARRAY, arg.allowNull(), 0); break; // array of anything (individual members cannot be restricted)
212+
case Type::Object: // if there is a classname and the argument is not nullable, it's simply the classname
213+
if (!arg.classname()) info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_OBJECT, arg.allowNull(), 0);
214+
// else info->type = (zend_type)arg.encoded();
215+
break;
216+
case Type::Callable: info->type = (zend_type) ZEND_TYPE_INIT_CODE(IS_CALLABLE, arg.allowNull(), 0); break; // anything that can be invoke
217+
218+
default: info->type = ZEND_TYPE_INIT_CODE(IS_UNDEF, 0, 0); break; // if not specified we allow anything
201219
#else
202220
case Type::Undefined: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // undefined means we'll accept any type
203221
case Type::Null: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // this is likely an error, what good would accepting NULL be? accept anything
@@ -216,7 +234,7 @@ class Callable
216234
default: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // if not specified we allow anything
217235
#endif
218236
}
219-
237+
#if PHP_VERSION_ID < 80000
220238
// from PHP 5.6 and onwards, an is_variadic property can be set, this
221239
// specifies whether this argument is the first argument that specifies
222240
// the type for a variable length list of arguments. For now we only
@@ -225,6 +243,7 @@ class Callable
225243

226244
// whether or not to pass the argument by reference
227245
info->pass_by_reference = arg.byReference();
246+
#endif
228247
}
229248

230249
/**

zend/classimpl.cpp

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ zend_function *ClassImpl::getStaticMethod(zend_class_entry *entry, zend_string *
284284
* @param object_ptr
285285
* @return int
286286
*/
287-
int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_function **func, zend_object **object_ptr)
287+
int ClassImpl::getClosure(ZEND_OBJECT_OR_ZVAL object, zend_class_entry **entry_ptr, zend_function **func, zend_object **object_ptr, zend_bool check_only)
288288
{
289289
// it is really unbelievable how the Zend engine manages to implement every feature
290290
// in a complete different manner. You would expect the __invoke() and the
@@ -314,7 +314,11 @@ int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_funct
314314

315315
// store pointer to ourselves (note that the entry_ptr is useless
316316
// inside this function as it is always uninitialized for some reason)
317+
#if PHP_VERSION_ID < 80000
317318
data->self = self(Z_OBJCE_P(object));
319+
#else
320+
data->self = self(object->ce);
321+
#endif
318322

319323
// assign this dynamically allocated variable to the func parameter
320324
// the cast is ok, because zend_internal_function is a member of the
@@ -323,7 +327,11 @@ int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_funct
323327

324328
// the object_ptr should be filled with the object on which the method is
325329
// called (otherwise the Zend engine tries to call the method statically)
330+
#if PHP_VERSION_ID < 80000
326331
*object_ptr = Z_OBJ_P(object);
332+
#else
333+
*object_ptr = object;
334+
#endif
327335

328336
// done
329337
return SUCCESS;
@@ -372,7 +380,11 @@ zend_object_handlers *ClassImpl::objectHandlers()
372380
_handlers.cast_object = &ClassImpl::cast;
373381

374382
// method to compare two objects
383+
#if PHP_VERSION_ID < 80000
375384
_handlers.compare_objects = &ClassImpl::compare;
385+
#else
386+
_handlers.compare = &ClassImpl::compare;
387+
#endif
376388

377389
// set the offset between our class implementation and
378390
// the zend_object member in the allocated structure
@@ -425,10 +437,17 @@ int ClassImpl::compare(zval *val1, zval *val2)
425437
catch (const NotImplemented &exception)
426438
{
427439
// it was not implemented, do we have a default?
440+
#if PHP_VERSION_ID < 80000
428441
if (!std_object_handlers.compare_objects) return 1;
429442

430443
// call default
431444
return std_object_handlers.compare_objects(val1, val2);
445+
#else
446+
if (!std_object_handlers.compare) return 1;
447+
448+
// call default
449+
return std_object_handlers.compare(val1, val2);
450+
#endif
432451
}
433452
catch (Throwable &throwable)
434453
{
@@ -447,14 +466,17 @@ int ClassImpl::compare(zval *val1, zval *val2)
447466
* @param type
448467
* @return int
449468
*/
450-
int ClassImpl::cast(zval *val, zval *retval, int type)
469+
int ClassImpl::cast(ZEND_OBJECT_OR_ZVAL val, zval *retval, int type)
451470
{
452471
// get the base c++ object
453472
Base *object = ObjectImpl::find(val)->object();
454473

455474
// retrieve the class entry linked to this object
475+
#if PHP_VERSION_ID < 80000
456476
auto *entry = Z_OBJCE_P(val);
457-
477+
#else
478+
auto *entry = val->ce;
479+
#endif
458480
// we need the C++ class meta-information object
459481
ClassBase *meta = self(entry)->_base;
460482

@@ -507,11 +529,14 @@ int ClassImpl::cast(zval *val, zval *retval, int type)
507529
* @param val The object to be cloned
508530
* @return zend_object The object to be created
509531
*/
510-
zend_object *ClassImpl::cloneObject(zval *val)
532+
zend_object *ClassImpl::cloneObject(ZEND_OBJECT_OR_ZVAL val)
511533
{
512534
// retrieve the class entry linked to this object
535+
#if PHP_VERSION_ID < 80000
513536
auto *entry = Z_OBJCE_P(val);
514-
537+
#else
538+
auto *entry = val->ce;
539+
#endif
515540
// we need the C++ class meta-information object
516541
ClassImpl *impl = self(entry);
517542
ClassBase *meta = impl->_base;
@@ -553,7 +578,7 @@ zend_object *ClassImpl::cloneObject(zval *val)
553578
* @param count
554579
* @return int
555580
*/
556-
int ClassImpl::countElements(zval *object, zend_long *count)
581+
int ClassImpl::countElements(ZEND_OBJECT_OR_ZVAL object, zend_long *count)
557582
{
558583
// does it implement the countable interface?
559584
Countable *countable = dynamic_cast<Countable*>(ObjectImpl::find(object)->object());
@@ -601,7 +626,7 @@ int ClassImpl::countElements(zval *object, zend_long *count)
601626
* @param rv Pointer to where to store the data
602627
* @return zval
603628
*/
604-
zval *ClassImpl::readDimension(zval *object, zval *offset, int type, zval *rv)
629+
zval *ClassImpl::readDimension(ZEND_OBJECT_OR_ZVAL object, zval *offset, int type, zval *rv)
605630
{
606631
// what to do with the type?
607632
//
@@ -663,7 +688,7 @@ zval *ClassImpl::readDimension(zval *object, zval *offset, int type, zval *rv)
663688
* @param value The new value
664689
* @return zval
665690
*/
666-
void ClassImpl::writeDimension(zval *object, zval *offset, zval *value)
691+
void ClassImpl::writeDimension(ZEND_OBJECT_OR_ZVAL object, zval *offset, zval *value)
667692
{
668693
// does it implement the arrayaccess interface?
669694
ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object)->object());
@@ -704,7 +729,7 @@ void ClassImpl::writeDimension(zval *object, zval *offset, zval *value)
704729
* @param check_empty Was this an isset() call, or an empty() call?
705730
* @return bool
706731
*/
707-
int ClassImpl::hasDimension(zval *object, zval *member, int check_empty)
732+
int ClassImpl::hasDimension(ZEND_OBJECT_OR_ZVAL object, zval *member, int check_empty)
708733
{
709734
// does it implement the arrayaccess interface?
710735
ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object)->object());
@@ -753,7 +778,7 @@ int ClassImpl::hasDimension(zval *object, zval *member, int check_empty)
753778
* @param object The object on which it is called
754779
* @param member The member to remove
755780
*/
756-
void ClassImpl::unsetDimension(zval *object, zval *member)
781+
void ClassImpl::unsetDimension(ZEND_OBJECT_OR_ZVAL object, zval *member)
757782
{
758783
// does it implement the arrayaccess interface?
759784
ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object)->object());
@@ -834,7 +859,7 @@ zval *ClassImpl::toZval(Value &&value, int type, zval *rv)
834859
* @param rv Pointer to where to store the data
835860
* @return val
836861
*/
837-
zval *ClassImpl::readProperty(zval *object, zval *name, int type, void **cache_slot, zval *rv)
862+
zval *ClassImpl::readProperty(ZEND_OBJECT_OR_ZVAL object, ZEND_STRING_OR_ZVAL name, int type, void **cache_slot, zval *rv)
838863
{
839864
// what to do with the type?
840865
//
@@ -857,7 +882,11 @@ zval *ClassImpl::readProperty(zval *object, zval *name, int type, void **cache_s
857882
Base *base = ObjectImpl::find(object)->object();
858883

859884
// retrieve the class entry linked to this object
885+
#if PHP_VERSION_ID < 80000
860886
auto *entry = Z_OBJCE_P(object);
887+
#else
888+
auto *entry = object->ce;
889+
#endif
861890

862891
// we need the C++ class meta-information object
863892
ClassImpl *impl = self(entry);
@@ -915,13 +944,17 @@ zval *ClassImpl::readProperty(zval *object, zval *name, int type, void **cache_s
915944
* @param cache_slot The cache slot used
916945
* @return zval
917946
*/
918-
PHP_WRITE_PROP_HANDLER_TYPE ClassImpl::writeProperty(zval *object, zval *name, zval *value, void **cache_slot)
947+
PHP_WRITE_PROP_HANDLER_TYPE ClassImpl::writeProperty(ZEND_OBJECT_OR_ZVAL object, ZEND_STRING_OR_ZVAL name, zval *value, void **cache_slot)
919948
{
920949
// retrieve the object and class
921950
Base *base = ObjectImpl::find(object)->object();
922951

923952
// retrieve the class entry linked to this object
953+
#if PHP_VERSION_ID < 80000
924954
auto *entry = Z_OBJCE_P(object);
955+
#else
956+
auto *entry = object->ce;
957+
#endif
925958

926959
// we need the C++ class meta-information object
927960
ClassImpl *impl = self(entry);
@@ -1006,7 +1039,7 @@ PHP_WRITE_PROP_HANDLER_TYPE ClassImpl::writeProperty(zval *object, zval *name, z
10061039
* @param cache_slot The cache slot used
10071040
* @return bool
10081041
*/
1009-
int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, void **cache_slot)
1042+
int ClassImpl::hasProperty(ZEND_OBJECT_OR_ZVAL object, ZEND_STRING_OR_ZVAL name, int has_set_exists, void **cache_slot)
10101043
{
10111044
// the default implementation throws an exception, if we catch that
10121045
// we know for sure that the user has not overridden the __isset method
@@ -1016,7 +1049,11 @@ int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, void **
10161049
Base *base = ObjectImpl::find(object)->object();
10171050

10181051
// retrieve the class entry linked to this object
1052+
#if PHP_VERSION_ID < 80000
10191053
auto *entry = Z_OBJCE_P(object);
1054+
#else
1055+
auto *entry = object->ce;
1056+
#endif
10201057

10211058
// we need the C++ class meta-information object
10221059
ClassImpl *impl = self(entry);
@@ -1070,15 +1107,18 @@ int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, void **
10701107
* @param member The member to remove
10711108
* @param cache_slot The cache slot used
10721109
*/
1073-
void ClassImpl::unsetProperty(zval *object, zval *member, void **cache_slot)
1110+
void ClassImpl::unsetProperty(ZEND_OBJECT_OR_ZVAL object, ZEND_STRING_OR_ZVAL member, void **cache_slot)
10741111
{
10751112
// the default implementation throws an exception, if we catch that
10761113
// we know for sure that the user has not overridden the __unset method
10771114
try
10781115
{
10791116
// retrieve the class entry linked to this object
1117+
#if PHP_VERSION_ID < 80000
10801118
auto *entry = Z_OBJCE_P(object);
1081-
1119+
#else
1120+
auto *entry = object->ce;
1121+
#endif
10821122
// we need the C++ class meta-information object
10831123
ClassImpl *impl = self(entry);
10841124

0 commit comments

Comments
 (0)