diff --git a/v8js_array_access.cc b/v8js_array_access.cc index 7c5218a..3151781 100644 --- a/v8js_array_access.cc +++ b/v8js_array_access.cc @@ -50,7 +50,11 @@ static zval v8js_array_access_dispatch(zend_object *object, const char *method_n fci.params = params; fci.object = object; +#if (PHP_MAJOR_VERSION < 8) fci.no_separation = 0; +#else + fci.named_params = NULL; +#endif zend_call_function(&fci, NULL); zval_dtor(&fci.function_name); diff --git a/v8js_class.cc b/v8js_class.cc index 4e9be67..9576898 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -506,7 +506,11 @@ static PHP_METHOD(V8Js, __construct) V8JS_GLOBAL(isolate)->DefineOwnProperty(context, object_name_js, php_obj, v8::ReadOnly); /* Export public property values */ + #if (PHP_MAJOR_VERSION < 8) HashTable *properties = zend_std_get_properties(getThis()); + #else + HashTable *properties = zend_std_get_properties(Z_OBJ_P(getThis())); + #endif zval *value; zend_string *member; @@ -665,7 +669,6 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze static void v8js_execute_script(zval *this_ptr, v8js_script *res, long flags, long time_limit, size_t memory_limit, zval **return_value) { v8js_ctx *c = Z_V8JS_CTX_OBJ_P(this_ptr); - if (res->ctx != c) { zend_error(E_WARNING, "Script resource from wrong V8Js object passed"); ZVAL_BOOL(*return_value, 0); @@ -1306,7 +1309,33 @@ const zend_function_entry v8js_methods[] = { /* {{{ */ /* V8Js object handlers */ +#if PHP_VERSION_ID >= 80000 +static SINCE74(zval*, void) v8js_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */ +{ + v8js_ctx *c = Z_V8JS_CTX_OBJ(object); + V8JS_CTX_PROLOGUE_EX(c, SINCE74(value,)); + /* Check whether member is public, if so, export to V8. */ + zend_property_info *property_info = zend_get_property_info(c->std.ce, member, 1); + + if(!property_info || + (property_info != ZEND_WRONG_PROPERTY_INFO && + (property_info->flags & ZEND_ACC_PUBLIC))) { + /* Global PHP JS object */ + v8::Local object_name_js = v8::Local::New(isolate, c->object_name); + v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(v8_context, object_name_js).ToLocalChecked()->ToObject(v8_context).ToLocalChecked(); + + if (ZSTR_LEN(member) > std::numeric_limits::max()) { + zend_throw_exception(php_ce_v8js_exception, + "Property name exceeds maximum supported length", 0); + return SINCE74(value,); + } + + /* Write value to PHP JS object */ + v8::Local key = V8JS_SYML(ZSTR_VAL(member), static_cast(ZSTR_LEN(member))); + jsobj->DefineOwnProperty(v8_context, key, zval_to_v8js(value, isolate), v8::ReadOnly); + } +#else static SINCE74(zval*, void) v8js_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ { v8js_ctx *c = Z_V8JS_CTX_OBJ_P(object); @@ -1314,6 +1343,7 @@ static SINCE74(zval*, void) v8js_write_property(zval *object, zval *member, zval /* Check whether member is public, if so, export to V8. */ zend_property_info *property_info = zend_get_property_info(c->std.ce, Z_STR_P(member), 1); + if(!property_info || (property_info != ZEND_WRONG_PROPERTY_INFO && (property_info->flags & ZEND_ACC_PUBLIC))) { @@ -1331,12 +1361,31 @@ static SINCE74(zval*, void) v8js_write_property(zval *object, zval *member, zval v8::Local key = V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); jsobj->DefineOwnProperty(v8_context, key, zval_to_v8js(value, isolate), v8::ReadOnly); } +#endif /* Write value to PHP object */ SINCE74(return,) std_object_handlers.write_property(object, member, value, NULL); } /* }}} */ +#if PHP_VERSION_ID >= 80000 +static void v8js_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */ +{ + V8JS_BEGIN_CTX_OBJ(c, object) + + /* Global PHP JS object */ + v8::Local object_name_js = v8::Local::New(isolate, c->object_name); + v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(v8_context, object_name_js).ToLocalChecked()->ToObject(v8_context).ToLocalChecked(); + + if (ZSTR_LEN(member) > std::numeric_limits::max()) { + zend_throw_exception(php_ce_v8js_exception, + "Property name exceeds maximum supported length", 0); + return; + } + + /* Delete value from PHP JS object */ + v8::Local key = V8JS_SYML(ZSTR_VAL(member), static_cast(ZSTR_LEN(member))); +#else static void v8js_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ { V8JS_BEGIN_CTX(c, object) @@ -1346,13 +1395,15 @@ static void v8js_unset_property(zval *object, zval *member, void **cache_slot) / v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(v8_context, object_name_js).ToLocalChecked()->ToObject(v8_context).ToLocalChecked(); if (Z_STRLEN_P(member) > std::numeric_limits::max()) { - zend_throw_exception(php_ce_v8js_exception, + zend_throw_exception(php_ce_v8js_exception, "Property name exceeds maximum supported length", 0); return; } /* Delete value from PHP JS object */ v8::Local key = V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); +#endif + jsobj->Delete(v8_context, key); /* Unset from PHP object */ diff --git a/v8js_class.h b/v8js_class.h index aaf2807..cabdee8 100644 --- a/v8js_class.h +++ b/v8js_class.h @@ -84,8 +84,13 @@ static inline struct v8js_ctx *v8js_ctx_fetch_object(zend_object *obj) { } #define Z_V8JS_CTX_OBJ_P(zv) v8js_ctx_fetch_object(Z_OBJ_P(zv)); +#define Z_V8JS_CTX_OBJ(zv) v8js_ctx_fetch_object(zv); +#if PHP_VERSION_ID >= 80000 +#define ZEND_ACC_DTOR 0 +#endif + PHP_MINIT_FUNCTION(v8js_class); #endif /* V8JS_CLASS_H */ diff --git a/v8js_convert.cc b/v8js_convert.cc index 8dc07f4..b70d20f 100644 --- a/v8js_convert.cc +++ b/v8js_convert.cc @@ -148,7 +148,11 @@ v8::Local zval_to_v8js(zval *value, v8::Isolate *isolate) /* {{{ */ ce = php_date_get_date_ce(); if (instanceof_function(Z_OBJCE_P(value), ce)) { zval dtval; + #if PHP_VERSION_ID >= 80000 + zend_call_method_with_0_params(Z_OBJ_P(value), NULL, NULL, "getTimestamp", &dtval); + #else zend_call_method_with_0_params(value, NULL, NULL, "getTimestamp", &dtval); + #endif v8::Date::New(isolate->GetEnteredOrMicrotaskContext(), ((double)Z_LVAL(dtval) * 1000.0)).ToLocal(&jsValue); zval_dtor(&dtval); } else diff --git a/v8js_exceptions.cc b/v8js_exceptions.cc index 4ec809b..89903d6 100644 --- a/v8js_exceptions.cc +++ b/v8js_exceptions.cc @@ -50,8 +50,14 @@ void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8:: object_init_ex(return_value, php_ce_v8js_script_exception); +#if PHP_VERSION_ID >= 80000 +#define PHPV8_EXPROP(type, name, value) \ + zend_update_property##type(php_ce_v8js_script_exception, Z_OBJ_P(return_value), #name, sizeof(#name) - 1, value); +#else #define PHPV8_EXPROP(type, name, value) \ zend_update_property##type(php_ce_v8js_script_exception, return_value, #name, sizeof(#name) - 1, value); +#endif + if (tc_message.IsEmpty()) { spprintf(&message_string, 0, "%s", exception_string); @@ -128,7 +134,19 @@ void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch) } } /* }}} */ - +#if PHP_VERSION_ID >= 80000 +#define V8JS_EXCEPTION_METHOD(property) \ + static PHP_METHOD(V8JsScriptException, get##property) \ + { \ + zval *value, rv; \ + \ + if (zend_parse_parameters_none() == FAILURE) { \ + return; \ + } \ + value = zend_read_property(php_ce_v8js_script_exception, Z_OBJ_P(getThis()), #property, sizeof(#property) - 1, 0, &rv); \ + RETURN_ZVAL(value, 1, 0); \ + } +#else #define V8JS_EXCEPTION_METHOD(property) \ static PHP_METHOD(V8JsScriptException, get##property) \ { \ @@ -140,6 +158,8 @@ void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch) value = zend_read_property(php_ce_v8js_script_exception, getThis(), #property, sizeof(#property) - 1, 0, &rv); \ RETURN_ZVAL(value, 1, 0); \ } +#endif + /* {{{ proto string V8JsEScriptxception::getJsFileName() */ diff --git a/v8js_methods.cc b/v8js_methods.cc index 7f7f926..519748b 100644 --- a/v8js_methods.cc +++ b/v8js_methods.cc @@ -311,8 +311,13 @@ V8JS_METHOD(require) ZVAL_STRING(¶ms[0], module_base_cstr); ZVAL_STRING(¶ms[1], module_id); + #if (PHP_MAJOR_VERSION < 8) call_result = call_user_function_ex(EG(function_table), NULL, &c->module_normaliser, &normaliser_result, 2, params, 0, NULL); + #else + call_result = call_user_function(EG(function_table), NULL, &c->module_normaliser, + &normaliser_result, 2, params); + #endif } isolate->Enter(); @@ -435,7 +440,11 @@ V8JS_METHOD(require) zend_try { ZVAL_STRING(¶ms[0], normalised_module_id); + #if (PHP_MAJOR_VERSION < 8) call_result = call_user_function_ex(EG(function_table), NULL, &c->module_loader, &module_code, 1, params, 0, NULL); + #else + call_result = call_user_function(EG(function_table), NULL, &c->module_loader, &module_code, 1, params); + #endif } zend_catch { v8js_terminate_execution(isolate); diff --git a/v8js_object_export.cc b/v8js_object_export.cc index b36a347..59263aa 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -137,8 +137,11 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, c } else { fci.params = NULL; } - +#if (PHP_MAJOR_VERSION < 8) fci.no_separation = 1; +#else + fci.named_params = NULL; +#endif info.GetReturnValue().Set(V8JS_NULL); { @@ -640,8 +643,12 @@ v8::Local v8js_named_property_callback(v8::Local property_n zval php_value; zend_object *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); + #if PHP_VERSION_ID >= 80000 + zend_object &zobject = *object; + #else zval zobject; ZVAL_OBJ(&zobject, object); + #endif v8js_function_tmpl_t *tmpl_ptr = reinterpret_cast(self->GetAlignedPointerFromInternalField(0)); v8::Local tmpl = v8::Local::New(isolate, *tmpl_ptr); @@ -796,7 +803,11 @@ v8::Local v8js_named_property_callback(v8::Local property_n const zend_object_handlers *h = object->handlers; if (callback_type == V8JS_PROP_QUERY) { + #if PHP_VERSION_ID >= 80000 + if (h->has_property(&zobject, Z_STR_P(&zname), 0, NULL)) { + #else if (h->has_property(&zobject, &zname, 0, NULL)) { + #endif ret_value = V8JS_UINT(v8::None); } else { ret_value = v8::Local(); // empty handle @@ -807,7 +818,11 @@ v8::Local v8js_named_property_callback(v8::Local property_n if(!property_info || (property_info != ZEND_WRONG_PROPERTY_INFO && property_info->flags & ZEND_ACC_PUBLIC)) { + #if PHP_VERSION_ID >= 80000 + h->unset_property(&zobject, Z_STR_P(&zname), NULL); + #else h->unset_property(&zobject, &zname, NULL); + #endif ret_value = V8JS_TRUE(); } else { diff --git a/v8js_v8.h b/v8js_v8.h index 7292ac0..67c9d7b 100644 --- a/v8js_v8.h +++ b/v8js_v8.h @@ -82,6 +82,11 @@ int v8js_get_properties_hash(v8::Local jsValue, HashTable *retval, in (ctx) = Z_V8JS_CTX_OBJ_P(object); \ V8JS_CTX_PROLOGUE(ctx); +#define V8JS_BEGIN_CTX_OBJ(ctx, object) \ + v8js_ctx *(ctx); \ + (ctx) = Z_V8JS_CTX_OBJ(object); \ + V8JS_CTX_PROLOGUE(ctx); + #if PHP_VERSION_ID < 70400 #define SINCE74(x,y) y diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index 11c4768..2fce6ba 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -21,7 +21,8 @@ #include "v8js_v8.h" #include "v8js_v8object_class.h" -extern "C" { +extern "C" +{ #include "ext/date/php_date.h" #include "ext/standard/php_string.h" #include "zend_interfaces.h" @@ -43,9 +44,38 @@ static zend_object_handlers v8js_v8generator_handlers; #define V8JS_V8_INVOKE_FUNC_NAME "V8Js::V8::Invoke" - /* V8 Object handlers */ +#if PHP_VERSION_ID >= 80000 +static int v8js_v8object_has_property(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot) /* {{{ */ +{ + int retval = false; + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ(object); + if (!obj->ctx) + { + zend_throw_exception(php_ce_v8js_exception, + "Can't access V8Object after V8Js instance is destroyed!", 0); + return false; + } + + V8JS_CTX_PROLOGUE_EX(obj->ctx, false); + v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); + v8::Local jsObj; + + if (!v8obj->IsObject() || !v8obj->ToObject(v8_context).ToLocal(&jsObj)) + { + return false; + } + + if (ZSTR_LEN(member) > std::numeric_limits::max()) + { + zend_throw_exception(php_ce_v8js_exception, + "Member name length exceeds maximum supported length", 0); + return false; + } + + v8::Local jsKey = V8JS_ZSYM(member); +#else static int v8js_v8object_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ { /* param has_set_exists: @@ -56,9 +86,10 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex int retval = false; v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); return false; } @@ -66,25 +97,28 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); v8::Local jsObj; - if (Z_TYPE_P(member) != IS_STRING || !v8obj->IsObject() || !v8obj->ToObject(v8_context).ToLocal(&jsObj)) { + if (Z_TYPE_P(member) != IS_STRING || !v8obj->IsObject() || !v8obj->ToObject(v8_context).ToLocal(&jsObj)) + { return false; } - if (Z_STRLEN_P(member) > std::numeric_limits::max()) { + if (Z_STRLEN_P(member) > std::numeric_limits::max()) + { zend_throw_exception(php_ce_v8js_exception, - "Member name length exceeds maximum supported length", 0); + "Member name length exceeds maximum supported length", 0); return false; } v8::Local jsKey = V8JS_ZSYM(Z_STR_P(member)); - +#endif /* Skip any prototype properties */ - if (!jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) - && !jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) { + if (!jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) && !jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) + { return false; } - if (has_set_exists == 2) { + if (has_set_exists == 2) + { /* property_exists(), that's enough! */ return true; } @@ -92,27 +126,30 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex /* We need to look at the value. */ v8::Local jsVal = jsObj->Get(v8_context, jsKey).ToLocalChecked(); - if (has_set_exists == 0 ) { + if (has_set_exists == 0) + { /* isset(): We make 'undefined' equivalent to 'null' */ - return !( jsVal->IsNull() || jsVal->IsUndefined() ); + return !(jsVal->IsNull() || jsVal->IsUndefined()); } /* empty() */ retval = jsVal->BooleanValue(isolate); /* for PHP compatibility, [] should also be empty */ - if (jsVal->IsArray() && retval) { + if (jsVal->IsArray() && retval) + { v8::Local array = v8::Local::Cast(jsVal); retval = (array->Length() != 0); } /* for PHP compatibility, '0' should also be empty */ v8::Local str; - if (jsVal->IsString() && retval && jsVal->ToString(v8_context).ToLocal(&str) - && str->Length() == 1) { + if (jsVal->IsString() && retval && jsVal->ToString(v8_context).ToLocal(&str) && str->Length() == 1) + { uint16_t c = 0; str->Write(isolate, &c, 0, 1); - if (c == '0') { + if (c == '0') + { retval = false; } } @@ -121,14 +158,43 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex } /* }}} */ +#if PHP_VERSION_ID >= 80000 +static zval *v8js_v8object_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv) /* {{{ */ +{ + zval *retval = rv; + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ(object); + + if (!obj->ctx) + { + zend_throw_exception(php_ce_v8js_exception, + "Can't access V8Object after V8Js instance is destroyed!", 0); + return retval; + } + + V8JS_CTX_PROLOGUE_EX(obj->ctx, retval); + v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); + + if (v8obj->IsObject()) + { + if (ZSTR_LEN(member) > std::numeric_limits::max()) + { + zend_throw_exception(php_ce_v8js_exception, + "Member name length exceeds maximum supported length", 0); + return retval; + } + + v8::Local jsKey = V8JS_ZSYM(member); + v8::Local jsObj = v8obj->ToObject(v8_context).ToLocalChecked(); +#else static zval *v8js_v8object_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ { zval *retval = rv; v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); return SINCE74(object, retval); } @@ -137,21 +203,23 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v if (Z_TYPE_P(member) == IS_STRING && v8obj->IsObject()) { - if (Z_STRLEN_P(member) > std::numeric_limits::max()) { + if (Z_STRLEN_P(member) > std::numeric_limits::max()) + { zend_throw_exception(php_ce_v8js_exception, - "Member name length exceeds maximum supported length", 0); + "Member name length exceeds maximum supported length", 0); return retval; } v8::Local jsKey = V8JS_ZSYM(Z_STR_P(member)); v8::Local jsObj = v8obj->ToObject(v8_context).ToLocalChecked(); - +#endif /* Skip any prototype properties */ - if (jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) - || jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) { + if (jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) || jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) + { v8::MaybeLocal jsVal = jsObj->Get(v8_context, jsKey); - - if (!jsVal.IsEmpty() && v8js_to_zval(jsVal.ToLocalChecked(), retval, obj->flags, isolate) == SUCCESS) { + + if (!jsVal.IsEmpty() && v8js_to_zval(jsVal.ToLocalChecked(), retval, obj->flags, isolate) == SUCCESS) + { return retval; } } @@ -161,73 +229,148 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v } /* }}} */ -static zval *v8js_v8object_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +#if PHP_VERSION_ID >= 80000 +static zval *v8js_v8object_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot) /* {{{ */ +#else +static zval *v8js_v8object_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +#endif { return NULL; } /* }}} */ -static SINCE74(zval*, void) v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ +#if PHP_VERSION_ID >= 80000 +static SINCE74(zval *, void) v8js_v8object_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */ { - v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ(object); - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); - return SINCE74(value,); + "Can't access V8Object after V8Js instance is destroyed!", 0); + return SINCE74(value, ); } - V8JS_CTX_PROLOGUE_EX(obj->ctx, SINCE74(value,)); + V8JS_CTX_PROLOGUE_EX(obj->ctx, SINCE74(value, )); v8::Local v8objHandle = v8::Local::New(isolate, obj->v8obj); - if (Z_STRLEN_P(member) > std::numeric_limits::max()) { + if (ZSTR_LEN(member) > std::numeric_limits::max()) + { zend_throw_exception(php_ce_v8js_exception, - "Member name length exceeds maximum supported length", 0); - return SINCE74(value,); + "Member name length exceeds maximum supported length", 0); + return SINCE74(value, ); } v8::Local v8obj; - if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) { - v8obj->CreateDataProperty(v8_context, V8JS_ZSYM(Z_STR_P(member)), zval_to_v8js(value, isolate)); + if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) + { + v8obj->CreateDataProperty(v8_context, V8JS_ZSYM(member), zval_to_v8js(value, isolate)); } - - return SINCE74(value,); -} -/* }}} */ - -static void v8js_v8object_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ +#else +static SINCE74(zval *, void) v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ { v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); + return SINCE74(value, ); + } + + V8JS_CTX_PROLOGUE_EX(obj->ctx, SINCE74(value, )); + v8::Local v8objHandle = v8::Local::New(isolate, obj->v8obj); + + if (Z_STRLEN_P(member) > std::numeric_limits::max()) + { + zend_throw_exception(php_ce_v8js_exception, + "Member name length exceeds maximum supported length", 0); + return SINCE74(value, ); + } + + v8::Local v8obj; + if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) + { + v8obj->CreateDataProperty(v8_context, V8JS_ZSYM(Z_STR_P(member)), zval_to_v8js(value, isolate)); + } +#endif + return SINCE74(value, ); +} +/* }}} */ + +#if PHP_VERSION_ID >= 80000 +static void v8js_v8object_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */ +{ + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ(object); + + if (!obj->ctx) + { + zend_throw_exception(php_ce_v8js_exception, + "Can't access V8Object after V8Js instance is destroyed!", 0); return; } V8JS_CTX_PROLOGUE(obj->ctx); v8::Local v8objHandle = v8::Local::New(isolate, obj->v8obj); - if (Z_STRLEN_P(member) > std::numeric_limits::max()) { + if (ZSTR_LEN(member) > std::numeric_limits::max()) + { zend_throw_exception(php_ce_v8js_exception, - "Member name length exceeds maximum supported length", 0); + "Member name length exceeds maximum supported length", 0); return; } v8::Local v8obj; - if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) { - v8obj->Delete(v8_context, V8JS_ZSYM(Z_STR_P(member))); + if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) + { + v8obj->Delete(v8_context, V8JS_ZSYM(member)); } } -/* }}} */ - -static HashTable *v8js_v8object_get_properties(zval *object) /* {{{ */ +#else +static void v8js_v8object_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ { v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); - if (obj->properties == NULL) { + if (!obj->ctx) + { + zend_throw_exception(php_ce_v8js_exception, + "Can't access V8Object after V8Js instance is destroyed!", 0); + return; + } + + V8JS_CTX_PROLOGUE(obj->ctx); + v8::Local v8objHandle = v8::Local::New(isolate, obj->v8obj); + + if (Z_STRLEN_P(member) > std::numeric_limits::max()) + { + zend_throw_exception(php_ce_v8js_exception, + "Member name length exceeds maximum supported length", 0); + return; + } + + v8::Local v8obj; + if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) + { + v8obj->Delete(v8_context, V8JS_ZSYM(Z_STR_P(member))); + } +} +#endif +/* }}} */ + +#if PHP_VERSION_ID >= 80000 +static HashTable *v8js_v8object_get_properties(zend_object *object) /* {{{ */ +{ + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ(object); +#else +static HashTable *v8js_v8object_get_properties(zval *object) /* {{{ */ +{ + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); +#endif + if (obj->properties == NULL) + { #if PHP_VERSION_ID < 70300 - if (GC_G(gc_active)) { + if (GC_G(gc_active)) + { /* the garbage collector is running, don't create more zvals */ return NULL; } @@ -236,26 +379,31 @@ static HashTable *v8js_v8object_get_properties(zval *object) /* {{{ */ ALLOC_HASHTABLE(obj->properties); zend_hash_init(obj->properties, 0, NULL, ZVAL_PTR_DTOR, 0); - if (!obj->ctx) { + if (!obj->ctx) + { /* Half-constructed object, probably due to unserialize call. * Just pass back properties hash so unserialize can write to * it (instead of crashing the engine). */ return obj->properties; } - } else if (!obj->properties->u.v.nIteratorsCount) { + } + else if (!obj->properties->u.v.nIteratorsCount) + { zend_hash_clean(obj->properties); } - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); return NULL; } V8JS_CTX_PROLOGUE_EX(obj->ctx, NULL); v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); - if (v8js_get_properties_hash(v8obj, obj->properties, obj->flags, isolate) == SUCCESS) { + if (v8js_get_properties_hash(v8obj, obj->properties, obj->flags, isolate) == SUCCESS) + { return obj->properties; } @@ -263,27 +411,156 @@ static HashTable *v8js_v8object_get_properties(zval *object) /* {{{ */ } /* }}} */ +#if PHP_VERSION_ID >= 80000 +static HashTable *v8js_v8object_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ +#else static HashTable *v8js_v8object_get_debug_info(zval *object, int *is_temp) /* {{{ */ +#endif { *is_temp = 0; return v8js_v8object_get_properties(object); } /* }}} */ +static ZEND_FUNCTION(zend_v8object_func) +{ + RETVAL_STR_COPY(EX(func)->common.function_name); + + zval *argv = NULL; + int argc = ZEND_NUM_ARGS(); + zend_string *method = EX(func)->common.function_name; + zend_object *object = Z_OBJ_P(getThis()); + + /* Cleanup trampoline */ + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE); + zend_string_release(EX(func)->common.function_name); + zend_free_trampoline(EX(func)); + EX(func) = NULL; + + v8js_v8object *obj = v8js_v8object_fetch_object(object); + + if (!obj->ctx) + { + zend_throw_exception(php_ce_v8js_exception, + "Can't access V8Object after V8Js instance is destroyed!", 0); + return; + } + + if (obj->v8obj.IsEmpty()) + { + return; + } + + if (ZSTR_LEN(method) > std::numeric_limits::max()) + { + zend_throw_exception(php_ce_v8js_exception, + "Method name length exceeds maximum supported length", 0); + return; + } + + if (argc > 0) + { + argv = (zval *)safe_emalloc(sizeof(zval), argc, 0); + zend_get_parameters_array_ex(argc, argv); + } + + /* std::function relies on its dtor to be executed, otherwise it leaks + * some memory on bailout. */ + { + std::function(v8::Isolate *)> v8_call = [obj, method, argc, argv, object, &return_value](v8::Isolate *isolate) + { + int i = 0; + + v8::Local v8_context = isolate->GetEnteredOrMicrotaskContext(); + v8::Local method_name = V8JS_SYML(ZSTR_VAL(method), static_cast(ZSTR_LEN(method))); + v8::Local v8obj = v8::Local::New(isolate, obj->v8obj)->ToObject(v8_context).ToLocalChecked(); + v8::Local thisObj; + v8::Local cb; + + if (method_name->Equals(v8_context, V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME)).FromMaybe(false)) + { + cb = v8::Local::Cast(v8obj); + } + else + { + v8::Local slot; + + if (!v8obj->Get(v8_context, method_name).ToLocal(&slot)) + { + return v8::MaybeLocal(); + } + + cb = v8::Local::Cast(slot); + } + + // If a method is invoked on V8Object, then set the object itself as + // "this" on JS side. Otherwise fall back to global object. + if (obj->std.ce == php_ce_v8object) + { + thisObj = v8obj; + } + else + { + thisObj = V8JS_GLOBAL(isolate); + } + + v8::Local *jsArgv = static_cast *>(alloca(sizeof(v8::Local) * argc)); + + for (i = 0; i < argc; i++) + { + new (&jsArgv[i]) v8::Local; + jsArgv[i] = v8::Local::New(isolate, zval_to_v8js(&argv[i], isolate)); + } + + v8::MaybeLocal result = cb->Call(v8_context, thisObj, argc, jsArgv); + + if (obj->std.ce == php_ce_v8object && !result.IsEmpty() && result.ToLocalChecked()->StrictEquals(thisObj)) + { + /* JS code did "return this", retain object identity */ + ZVAL_OBJ(return_value, object); + zval_copy_ctor(return_value); + result = v8::MaybeLocal(); + } + + return result; + }; + + v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call); + } + + if (argc > 0) + { + efree(argv); + } + + if (V8JSG(fatal_error_abort)) + { + /* Check for fatal error marker possibly set by v8js_error_handler; just + * rethrow the error since we're now out of V8. */ + zend_bailout(); + } +} + static zend_function *v8js_v8object_get_method(zend_object **object_ptr, zend_string *method, const zval *key) /* {{{ */ { v8js_v8object *obj = v8js_v8object_fetch_object(*object_ptr); +#if PHP_VERSION_ID < 80000 zend_function *f; +#else + zend_internal_function *f; +#endif - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); return NULL; } - if (ZSTR_LEN(method) > std::numeric_limits::max()) { + if (ZSTR_LEN(method) > std::numeric_limits::max()) + { zend_throw_exception(php_ce_v8js_exception, - "Method name length exceeds maximum supported length", 0); + "Method name length exceeds maximum supported length", 0); return NULL; } @@ -291,18 +568,25 @@ static zend_function *v8js_v8object_get_method(zend_object **object_ptr, zend_st v8::Local jsKey = V8JS_STRL(ZSTR_VAL(method), static_cast(ZSTR_LEN(method))); v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); - if (!obj->v8obj.IsEmpty() && v8obj->IsObject() && !v8obj->IsFunction()) { + if (!obj->v8obj.IsEmpty() && v8obj->IsObject() && !v8obj->IsFunction()) + { v8::Local jsObj; v8::Local jsObjSlot; - if (v8obj->ToObject(v8_context).ToLocal(&jsObj) - && jsObj->Has(v8_context, jsKey).FromMaybe(false) - && jsObj->Get(v8_context, jsKey).ToLocal(&jsObjSlot) - && jsObjSlot->IsFunction()) { - f = (zend_function *) ecalloc(1, sizeof(*f)); + if (v8obj->ToObject(v8_context).ToLocal(&jsObj) && jsObj->Has(v8_context, jsKey).FromMaybe(false) && jsObj->Get(v8_context, jsKey).ToLocal(&jsObjSlot) && jsObjSlot->IsFunction()) + { +#if PHP_VERSION_ID < 80000 + f = (zend_function *)ecalloc(1, sizeof(*f)); f->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY; f->common.function_name = zend_string_copy(method); return f; +#else + f = (zend_internal_function *)ecalloc(1, sizeof(*f)); + f->type = ZEND_ACC_CALL_VIA_HANDLER; + f->handler = ZEND_FN(zend_v8object_func); + f->function_name = zend_string_copy(method); + return (zend_function *)f; +#endif } } @@ -317,31 +601,36 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I v8js_v8object *obj = v8js_v8object_fetch_object(object); - if (!obj->ctx) { + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); return FAILURE; } - if (obj->v8obj.IsEmpty()) { + if (obj->v8obj.IsEmpty()) + { return FAILURE; } - if (ZSTR_LEN(method) > std::numeric_limits::max()) { + if (ZSTR_LEN(method) > std::numeric_limits::max()) + { zend_throw_exception(php_ce_v8js_exception, - "Method name length exceeds maximum supported length", 0); + "Method name length exceeds maximum supported length", 0); return FAILURE; } - if (argc > 0) { - argv = (zval*)safe_emalloc(sizeof(zval), argc, 0); + if (argc > 0) + { + argv = (zval *)safe_emalloc(sizeof(zval), argc, 0); zend_get_parameters_array_ex(argc, argv); } /* std::function relies on its dtor to be executed, otherwise it leaks * some memory on bailout. */ { - std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value](v8::Isolate *isolate) { + std::function(v8::Isolate *)> v8_call = [obj, method, argc, argv, object, &return_value](v8::Isolate *isolate) + { int i = 0; v8::Local v8_context = isolate->GetEnteredOrMicrotaskContext(); @@ -350,12 +639,16 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I v8::Local thisObj; v8::Local cb; - if (method_name->Equals(v8_context, V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME)).FromMaybe(false)) { + if (method_name->Equals(v8_context, V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME)).FromMaybe(false)) + { cb = v8::Local::Cast(v8obj); - } else { + } + else + { v8::Local slot; - if (!v8obj->Get(v8_context, method_name).ToLocal(&slot)) { + if (!v8obj->Get(v8_context, method_name).ToLocal(&slot)) + { return v8::MaybeLocal(); } @@ -364,23 +657,27 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I // If a method is invoked on V8Object, then set the object itself as // "this" on JS side. Otherwise fall back to global object. - if (obj->std.ce == php_ce_v8object) { + if (obj->std.ce == php_ce_v8object) + { thisObj = v8obj; } - else { + else + { thisObj = V8JS_GLOBAL(isolate); } v8::Local *jsArgv = static_cast *>(alloca(sizeof(v8::Local) * argc)); - for (i = 0; i < argc; i++) { - new(&jsArgv[i]) v8::Local; + for (i = 0; i < argc; i++) + { + new (&jsArgv[i]) v8::Local; jsArgv[i] = v8::Local::New(isolate, zval_to_v8js(&argv[i], isolate)); } v8::MaybeLocal result = cb->Call(v8_context, thisObj, argc, jsArgv); - if (obj->std.ce == php_ce_v8object && !result.IsEmpty() && result.ToLocalChecked()->StrictEquals(thisObj)) { + if (obj->std.ce == php_ce_v8object && !result.IsEmpty() && result.ToLocalChecked()->StrictEquals(thisObj)) + { /* JS code did "return this", retain object identity */ ZVAL_OBJ(return_value, object); zval_copy_ctor(return_value); @@ -393,11 +690,13 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call); } - if (argc > 0) { + if (argc > 0) + { efree(argv); } - if(V8JSG(fatal_error_abort)) { + if (V8JSG(fatal_error_abort)) + { /* Check for fatal error marker possibly set by v8js_error_handler; just * rethrow the error since we're now out of V8. */ zend_bailout(); @@ -407,32 +706,52 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I } /* }}} */ +#if PHP_VERSION_ID >= 80000 +static int v8js_v8object_get_closure(zend_object *object, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **zobj_ptr, bool call) /* {{{ */ +{ + zend_internal_function *invoke; + v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ(object); +#else static int v8js_v8object_get_closure(zval *object, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **zobj_ptr) /* {{{ */ { zend_function *invoke; v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); - - if (!obj->ctx) { +#endif + if (!obj->ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Object after V8Js instance is destroyed!", 0); + "Can't access V8Object after V8Js instance is destroyed!", 0); return FAILURE; } V8JS_CTX_PROLOGUE_EX(obj->ctx, FAILURE); v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); - if (!v8obj->IsFunction()) { + if (!v8obj->IsFunction()) + { return FAILURE; } - invoke = (zend_function *) ecalloc(1, sizeof(*invoke)); +#if PHP_VERSION_ID < 80000 + invoke = (zend_function *)ecalloc(1, sizeof(*invoke)); invoke->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY; invoke->common.function_name = zend_string_init(V8JS_V8_INVOKE_FUNC_NAME, sizeof(V8JS_V8_INVOKE_FUNC_NAME) - 1, 0); - *fptr_ptr = invoke; +#else + invoke = (zend_internal_function *)ecalloc(1, sizeof(*invoke)); + invoke->type = ZEND_ACC_CALL_VIA_HANDLER; + invoke->handler = ZEND_FN(zend_v8object_func); + invoke->function_name = zend_string_init(V8JS_V8_INVOKE_FUNC_NAME, sizeof(V8JS_V8_INVOKE_FUNC_NAME) - 1, 0); + *fptr_ptr = (zend_function *)invoke; +#endif - if (zobj_ptr) { + if (zobj_ptr) + { +#if PHP_VERSION_ID >= 80000 + *zobj_ptr = object; +#else *zobj_ptr = Z_OBJ_P(object); +#endif } *ce_ptr = NULL; @@ -445,7 +764,8 @@ static void v8js_v8object_free_storage(zend_object *object) /* {{{ */ { v8js_v8object *c = v8js_v8object_fetch_object(object); - if (c->properties) { + if (c->properties) + { zend_hash_destroy(c->properties); FREE_HASHTABLE(c->properties); c->properties = NULL; @@ -453,7 +773,8 @@ static void v8js_v8object_free_storage(zend_object *object) /* {{{ */ zend_object_std_dtor(&c->std); - if(c->ctx) { + if (c->ctx) + { c->v8obj.Reset(); c->ctx->v8js_v8objects.remove(c); } @@ -463,11 +784,11 @@ static void v8js_v8object_free_storage(zend_object *object) /* {{{ */ static zend_object *v8js_v8object_new(zend_class_entry *ce) /* {{{ */ { v8js_v8object *c; - c = (v8js_v8object *) ecalloc(1, sizeof(v8js_v8object) + zend_object_properties_size(ce)); + c = (v8js_v8object *)ecalloc(1, sizeof(v8js_v8object) + zend_object_properties_size(ce)); zend_object_std_init(&c->std, ce); c->std.handlers = &v8js_v8object_handlers; - new(&c->v8obj) v8::Persistent(); + new (&c->v8obj) v8::Persistent(); return &c->std; } @@ -480,10 +801,10 @@ static zend_object *v8js_v8object_new(zend_class_entry *ce) /* {{{ */ /* {{{ proto V8Object::__construct() */ -PHP_METHOD(V8Object,__construct) +PHP_METHOD(V8Object, __construct) { zend_throw_exception(php_ce_v8js_exception, - "Can't directly construct V8 objects!", 0); + "Can't directly construct V8 objects!", 0); RETURN_FALSE; } /* }}} */ @@ -493,7 +814,7 @@ PHP_METHOD(V8Object,__construct) PHP_METHOD(V8Object, __sleep) { zend_throw_exception(php_ce_v8js_exception, - "You cannot serialize or unserialize V8Object instances", 0); + "You cannot serialize or unserialize V8Object instances", 0); RETURN_FALSE; } /* }}} */ @@ -503,17 +824,17 @@ PHP_METHOD(V8Object, __sleep) PHP_METHOD(V8Object, __wakeup) { zend_throw_exception(php_ce_v8js_exception, - "You cannot serialize or unserialize V8Object instances", 0); + "You cannot serialize or unserialize V8Object instances", 0); RETURN_FALSE; } /* }}} */ /* {{{ proto V8Function::__construct() */ -PHP_METHOD(V8Function,__construct) +PHP_METHOD(V8Function, __construct) { zend_throw_exception(php_ce_v8js_exception, - "Can't directly construct V8 objects!", 0); + "Can't directly construct V8 objects!", 0); RETURN_FALSE; } /* }}} */ @@ -523,7 +844,7 @@ PHP_METHOD(V8Function,__construct) PHP_METHOD(V8Function, __sleep) { zend_throw_exception(php_ce_v8js_exception, - "You cannot serialize or unserialize V8Function instances", 0); + "You cannot serialize or unserialize V8Function instances", 0); RETURN_FALSE; } /* }}} */ @@ -533,12 +854,11 @@ PHP_METHOD(V8Function, __sleep) PHP_METHOD(V8Function, __wakeup) { zend_throw_exception(php_ce_v8js_exception, - "You cannot serialize or unserialize V8Function instances", 0); + "You cannot serialize or unserialize V8Function instances", 0); RETURN_FALSE; } /* }}} */ - static void v8js_v8generator_free_storage(zend_object *object) /* {{{ */ { v8js_v8generator *c = v8js_v8generator_fetch_object(object); @@ -551,11 +871,11 @@ static void v8js_v8generator_free_storage(zend_object *object) /* {{{ */ static zend_object *v8js_v8generator_new(zend_class_entry *ce) /* {{{ */ { v8js_v8generator *c; - c = (v8js_v8generator *) ecalloc(1, sizeof(v8js_v8generator) + zend_object_properties_size(ce)); + c = (v8js_v8generator *)ecalloc(1, sizeof(v8js_v8generator) + zend_object_properties_size(ce)); zend_object_std_init(&c->v8obj.std, ce); c->v8obj.std.handlers = &v8js_v8generator_handlers; - new(&c->v8obj.v8obj) v8::Persistent(); + new (&c->v8obj.v8obj) v8::Persistent(); return &c->v8obj.std; } @@ -563,35 +883,39 @@ static zend_object *v8js_v8generator_new(zend_class_entry *ce) /* {{{ */ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */ { - if (!g->v8obj.ctx) { + if (!g->v8obj.ctx) + { zend_throw_exception(php_ce_v8js_exception, - "Can't access V8Generator after V8Js instance is destroyed!", 0); + "Can't access V8Generator after V8Js instance is destroyed!", 0); return; } /* std::function relies on its dtor to be executed, otherwise it leaks * some memory on bailout. */ { - std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [g](v8::Isolate *isolate) { + std::function(v8::Isolate *)> v8_call = [g](v8::Isolate *isolate) + { v8::Local v8_context = isolate->GetEnteredOrMicrotaskContext(); v8::Local method_name = V8JS_SYM("next"); v8::Local v8obj = v8::Local::New(isolate, g->v8obj.v8obj)->ToObject(v8_context).ToLocalChecked(); - v8::Local cb = v8::Local::Cast(v8obj->Get(v8_context, method_name).ToLocalChecked());; + v8::Local cb = v8::Local::Cast(v8obj->Get(v8_context, method_name).ToLocalChecked()); + ; v8::MaybeLocal result = cb->Call(v8_context, v8obj, 0, NULL); - if(result.IsEmpty()) { + if (result.IsEmpty()) + { /* cb->Call probably threw (and already threw a zend exception), just return */ return V8JS_NULL; } - if(!result.ToLocalChecked()->IsObject()) { + if (!result.ToLocalChecked()->IsObject()) + { zend_throw_exception(php_ce_v8js_exception, - "V8Generator returned non-object on next()", 0); + "V8Generator returned non-object on next()", 0); return V8JS_NULL; } - v8::Local resultObj = result.ToLocalChecked()->ToObject(v8_context).ToLocalChecked(); v8::Local val = resultObj->Get(v8_context, V8JS_SYM("value")).ToLocalChecked(); v8::Local done = resultObj->Get(v8_context, V8JS_SYM("done")).ToLocalChecked(); @@ -607,7 +931,8 @@ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */ v8js_v8_call(g->v8obj.ctx, NULL, g->v8obj.flags, g->v8obj.ctx->time_limit, g->v8obj.ctx->memory_limit, v8_call); } - if(V8JSG(fatal_error_abort)) { + if (V8JSG(fatal_error_abort)) + { /* Check for fatal error marker possibly set by v8js_error_handler; just * rethrow the error since we're now out of V8. */ zend_bailout(); @@ -619,7 +944,8 @@ static zend_function *v8js_v8generator_get_method(zend_object **object_ptr, zend { zend_function *result = std_object_handlers.get_method(object_ptr, method, key); - if(!result) { + if (!result) + { result = v8js_v8object_get_method(object_ptr, method, key); } @@ -629,10 +955,10 @@ static zend_function *v8js_v8generator_get_method(zend_object **object_ptr, zend /* {{{ proto V8Generator::__construct() */ -PHP_METHOD(V8Generator,__construct) +PHP_METHOD(V8Generator, __construct) { zend_throw_exception(php_ce_v8js_exception, - "Can't directly construct V8 objects!", 0); + "Can't directly construct V8 objects!", 0); RETURN_FALSE; } /* }}} */ @@ -642,7 +968,7 @@ PHP_METHOD(V8Generator,__construct) PHP_METHOD(V8Generator, __sleep) { zend_throw_exception(php_ce_v8js_exception, - "You cannot serialize or unserialize V8Generator instances", 0); + "You cannot serialize or unserialize V8Generator instances", 0); RETURN_FALSE; } /* }}} */ @@ -652,7 +978,7 @@ PHP_METHOD(V8Generator, __sleep) PHP_METHOD(V8Generator, __wakeup) { zend_throw_exception(php_ce_v8js_exception, - "You cannot serialize or unserialize V8Generator instances", 0); + "You cannot serialize or unserialize V8Generator instances", 0); RETURN_FALSE; } /* }}} */ @@ -663,7 +989,8 @@ PHP_METHOD(V8Generator, current) { v8js_v8generator *g = Z_V8JS_V8GENERATOR_OBJ_P(getThis()); - if(!g->primed) { + if (!g->primed) + { v8js_v8generator_next(g); } @@ -694,10 +1021,10 @@ PHP_METHOD(V8Generator, rewind) { v8js_v8generator *g = Z_V8JS_V8GENERATOR_OBJ_P(getThis()); - if(g->primed) { + if (g->primed) + { zend_throw_exception(php_ce_v8js_exception, - "V8Generator::rewind not supported by ES6", 0); - + "V8Generator::rewind not supported by ES6", 0); } RETURN_FALSE; @@ -710,7 +1037,8 @@ PHP_METHOD(V8Generator, valid) { v8js_v8generator *g = Z_V8JS_V8GENERATOR_OBJ_P(getThis()); - if(!g->primed) { + if (!g->primed) + { v8js_v8generator_next(g); } @@ -718,18 +1046,20 @@ PHP_METHOD(V8Generator, valid) } /* }}} */ - void v8js_v8object_create(zval *res, v8::Local value, int flags, v8::Isolate *isolate) /* {{{ */ { - v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8js_ctx *ctx = (v8js_ctx *)isolate->GetData(0); - if(value->IsGeneratorObject()) { + if (value->IsGeneratorObject()) + { object_init_ex(res, php_ce_v8generator); } - else if(value->IsFunction()) { + else if (value->IsFunction()) + { object_init_ex(res, php_ce_v8function); } - else { + else + { object_init_ex(res, php_ce_v8object); } @@ -743,23 +1073,45 @@ void v8js_v8object_create(zval *res, v8::Local value, int flags, v8:: } /* }}} */ +ZEND_BEGIN_ARG_INFO(arginfo_v8object_construct, 0) +ZEND_END_ARG_INFO() -static const zend_function_entry v8js_v8object_methods[] = { /* {{{ */ - PHP_ME(V8Object, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) - PHP_ME(V8Object, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - PHP_ME(V8Object, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - {NULL, NULL, NULL} -}; +ZEND_BEGIN_ARG_INFO(arginfo_v8object_sleep, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_v8object_wakeup, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry v8js_v8object_methods[] = {/* {{{ */ + PHP_ME(V8Object, __construct, arginfo_v8object_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(V8Object, __sleep, arginfo_v8object_sleep, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) + PHP_ME(V8Object, __wakeup, arginfo_v8object_wakeup, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL){NULL, NULL, NULL}}; /* }}} */ -static const zend_function_entry v8js_v8function_methods[] = { /* {{{ */ - PHP_ME(V8Function, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) - PHP_ME(V8Function, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - PHP_ME(V8Function, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - {NULL, NULL, NULL} -}; +ZEND_BEGIN_ARG_INFO(arginfo_v8function_construct, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_v8function_sleep, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_v8function_wakeup, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry v8js_v8function_methods[] = {/* {{{ */ + PHP_ME(V8Function, __construct, arginfo_v8function_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(V8Function, __sleep, arginfo_v8function_sleep, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) + PHP_ME(V8Function, __wakeup, arginfo_v8function_wakeup, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL){NULL, NULL, NULL}}; /* }}} */ +ZEND_BEGIN_ARG_INFO(arginfo_v8generator_construct, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_v8generator_sleep, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_v8generator_wakeup, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_v8generator_current, 0) ZEND_END_ARG_INFO() @@ -775,22 +1127,20 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_v8generator_valid, 0) ZEND_END_ARG_INFO() -static const zend_function_entry v8js_v8generator_methods[] = { /* {{{ */ - PHP_ME(V8Generator, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) - PHP_ME(V8Generator, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - PHP_ME(V8Generator, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) +static const zend_function_entry v8js_v8generator_methods[] = {/* {{{ */ + PHP_ME(V8Generator, __construct, arginfo_v8generator_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(V8Generator, __sleep, arginfo_v8generator_sleep, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) + PHP_ME(V8Generator, __wakeup, arginfo_v8generator_wakeup, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL) - PHP_ME(V8Generator, current, arginfo_v8generator_current, ZEND_ACC_PUBLIC) - PHP_ME(V8Generator, key, arginfo_v8generator_key, ZEND_ACC_PUBLIC) - PHP_ME(V8Generator, next, arginfo_v8generator_next, ZEND_ACC_PUBLIC) - PHP_ME(V8Generator, rewind, arginfo_v8generator_rewind, ZEND_ACC_PUBLIC) - PHP_ME(V8Generator, valid, arginfo_v8generator_valid, ZEND_ACC_PUBLIC) + PHP_ME(V8Generator, current, arginfo_v8generator_current, ZEND_ACC_PUBLIC) + PHP_ME(V8Generator, key, arginfo_v8generator_key, ZEND_ACC_PUBLIC) + PHP_ME(V8Generator, next, arginfo_v8generator_next, ZEND_ACC_PUBLIC) + PHP_ME(V8Generator, rewind, arginfo_v8generator_rewind, ZEND_ACC_PUBLIC) + PHP_ME(V8Generator, valid, arginfo_v8generator_valid, ZEND_ACC_PUBLIC) - {NULL, NULL, NULL} -}; + {NULL, NULL, NULL}}; /* }}} */ - PHP_MINIT_FUNCTION(v8js_v8object_class) /* {{{ */ { zend_class_entry ce; @@ -815,7 +1165,6 @@ PHP_MINIT_FUNCTION(v8js_v8object_class) /* {{{ */ zend_class_implements(php_ce_v8generator, 1, zend_ce_iterator); - /* V8 handlers */ memcpy(&v8js_v8object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); v8js_v8object_handlers.clone_obj = NULL; @@ -827,7 +1176,9 @@ PHP_MINIT_FUNCTION(v8js_v8object_class) /* {{{ */ v8js_v8object_handlers.unset_property = v8js_v8object_unset_property; v8js_v8object_handlers.get_properties = v8js_v8object_get_properties; v8js_v8object_handlers.get_method = v8js_v8object_get_method; +#if PHP_VERSION_ID < 80000 v8js_v8object_handlers.call_method = v8js_v8object_call_method; +#endif v8js_v8object_handlers.get_debug_info = v8js_v8object_get_debug_info; v8js_v8object_handlers.get_closure = v8js_v8object_get_closure; v8js_v8object_handlers.offset = XtOffsetOf(struct v8js_v8object, std); @@ -842,7 +1193,6 @@ PHP_MINIT_FUNCTION(v8js_v8object_class) /* {{{ */ return SUCCESS; } /* }}} */ - /* * Local variables: * tab-width: 4 diff --git a/v8js_v8object_class.h b/v8js_v8object_class.h index b342bd6..0bb7ed0 100644 --- a/v8js_v8object_class.h +++ b/v8js_v8object_class.h @@ -35,7 +35,7 @@ static inline v8js_v8object *v8js_v8object_fetch_object(zend_object *obj) { } #define Z_V8JS_V8OBJECT_OBJ_P(zv) v8js_v8object_fetch_object(Z_OBJ_P(zv)); - +#define Z_V8JS_V8OBJECT_OBJ(zv) v8js_v8object_fetch_object(zv); /* {{{ Generator container */ struct v8js_v8generator {