diff --git a/v8js_array_access.cc b/v8js_array_access.cc index c9ca933..3675213 100644 --- a/v8js_array_access.cc +++ b/v8js_array_access.cc @@ -56,7 +56,7 @@ static zval v8js_array_access_dispatch(zend_object *object, const char *method_n -void v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo& info) /* {{{ */ +V8JS_INTERCEPTED v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo& info) /* {{{ */ { v8::Isolate *isolate = info.GetIsolate(); v8::Local self = info.Holder(); @@ -70,12 +70,17 @@ void v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo ret_value = zval_to_v8js(&php_value, isolate); zval_ptr_dtor(&php_value); - info.GetReturnValue().Set(ret_value); + if (ret_value.IsEmpty()) { + return V8JS_INTERCEPTED_NO; + } else { + info.GetReturnValue().Set(ret_value); + return V8JS_INTERCEPTED_YES; + } } /* }}} */ -void v8js_array_access_setter(uint32_t index, v8::Local value, - const v8::PropertyCallbackInfo& info) /* {{{ */ +V8JS_INTERCEPTED v8js_array_access_setter(uint32_t index, v8::Local value, + const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info) /* {{{ */ { v8::Isolate *isolate = info.GetIsolate(); v8::Local self = info.Holder(); @@ -86,20 +91,22 @@ void v8js_array_access_setter(uint32_t index, v8::Local value, ZVAL_UNDEF(&zvalue); if (v8js_to_zval(value, &zvalue, 0, isolate) != SUCCESS) { - info.GetReturnValue().Set(v8::Local()); - return; + return V8JS_INTERCEPTED_NO; } zval php_value = v8js_array_access_dispatch(object, "offsetSet", 2, index, zvalue); zval_ptr_dtor(&php_value); +#if !PHP_V8_HAS_INTERCEPTED /* simply pass back the value to tell we intercepted the call * as the offsetSet function returns void. */ info.GetReturnValue().Set(value); +#endif /* if PHP wanted to hold on to this value, zend_call_function would * have bumped the refcount. */ zval_ptr_dtor(&zvalue); + return V8JS_INTERCEPTED_YES; } /* }}} */ @@ -159,7 +166,7 @@ static void v8js_array_access_length(v8::Local property, const v8::P } /* }}} */ -void v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo& info) /* {{{ */ +V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo& info) /* {{{ */ { v8::Isolate *isolate = info.GetIsolate(); v8::Local self = info.Holder(); @@ -173,10 +180,11 @@ void v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo& info) /* {{{ */ +V8JS_INTERCEPTED v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo& info) /* {{{ */ { v8::Isolate *isolate = info.GetIsolate(); v8::Local self = info.Holder(); @@ -187,7 +195,10 @@ void v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo& inf -void v8js_array_access_named_getter(v8::Local property_name, const v8::PropertyCallbackInfo &info) /* {{{ */ +V8JS_INTERCEPTED v8js_array_access_named_getter(v8::Local property_name, const v8::PropertyCallbackInfo &info) /* {{{ */ { v8::Local property = v8::Local::Cast(property_name); v8::Isolate *isolate = info.GetIsolate(); @@ -226,10 +237,10 @@ void v8js_array_access_named_getter(v8::Local property_name, const v8: if(strcmp(name, "length") == 0) { v8js_array_access_length(property, info); - return; + return V8JS_INTERCEPTED_YES; } - v8::Local ret_value = v8js_named_property_callback(property, info, V8JS_PROP_GETTER); + v8::Local ret_value = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_GETTER); if(ret_value.IsEmpty()) { v8::Local arr = v8::Array::New(isolate); @@ -250,6 +261,7 @@ void v8js_array_access_named_getter(v8::Local property_name, const v8: } info.GetReturnValue().Set(ret_value); + return V8JS_INTERCEPTED_YES; } /* }}} */ diff --git a/v8js_array_access.h b/v8js_array_access.h index 283e1cb..6884c7b 100644 --- a/v8js_array_access.h +++ b/v8js_array_access.h @@ -14,18 +14,18 @@ #define V8JS_ARRAY_ACCESS_H /* Indexed Property Handlers */ -void v8js_array_access_getter(uint32_t index, - const v8::PropertyCallbackInfo& info); -void v8js_array_access_setter(uint32_t index, v8::Local value, +V8JS_INTERCEPTED v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo& info); +V8JS_INTERCEPTED v8js_array_access_setter(uint32_t index, v8::Local value, + const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info); void v8js_array_access_enumerator(const v8::PropertyCallbackInfo& info); -void v8js_array_access_deleter(uint32_t index, +V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo& info); -void v8js_array_access_query(uint32_t index, +V8JS_INTERCEPTED v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo& info); /* Named Property Handlers */ -void v8js_array_access_named_getter(v8::Local property, +V8JS_INTERCEPTED v8js_array_access_named_getter(v8::Local property, const v8::PropertyCallbackInfo &info); #endif /* V8JS_ARRAY_ACCESS_H */ diff --git a/v8js_class.cc b/v8js_class.cc index 5b5ac51..767ff67 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -53,7 +53,7 @@ extern const zend_function_entry v8js_methods[]; typedef struct _v8js_script { char *name; v8js_ctx *ctx; - v8::Persistent> *script; + v8::Global *script; } v8js_script; static void v8js_script_free(v8js_script *res); @@ -95,11 +95,11 @@ static void v8js_free_storage(zend_object *object) /* {{{ */ } c->object_name.Reset(); - c->object_name.~Persistent(); + c->object_name.~Global(); c->global_template.Reset(); - c->global_template.~Persistent(); + c->global_template.~Global(); c->array_tmpl.Reset(); - c->array_tmpl.~Persistent(); + c->array_tmpl.~Global(); /* Clear persistent call_impl & method_tmpls templates */ for (std::map::iterator it = c->call_impls.begin(); @@ -133,7 +133,7 @@ static void v8js_free_storage(zend_object *object) /* {{{ */ if (!c->context.IsEmpty()) { c->context.Reset(); } - c->context.~Persistent(); + c->context.~Global(); /* Dispose yet undisposed weak refs */ for (std::map::iterator it = c->weak_objects.begin(); @@ -208,10 +208,10 @@ static zend_object* v8js_new(zend_class_entry *ce) /* {{{ */ c->std.handlers = &v8js_object_handlers; - new(&c->object_name) v8::Persistent(); - new(&c->context) v8::Persistent(); - new(&c->global_template) v8::Persistent(); - new(&c->array_tmpl) v8::Persistent(); + new(&c->object_name) v8::Global(); + new(&c->context) v8::Global(); + new(&c->global_template) v8::Global(); + new(&c->array_tmpl) v8::Global(); new(&c->modules_stack) std::vector(); new(&c->modules_loaded) std::map; @@ -524,7 +524,11 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze v8::Local sname = identifier ? V8JS_ZSTR(identifier) : V8JS_SYM("V8Js::compileString()"); - v8::ScriptOrigin origin(isolate, sname); +#if PHP_V8_API_VERSION >= 12002000 + v8::ScriptOrigin origin(sname); +#else + v8::ScriptOrigin origin(c->isolate, sname); +#endif if (ZSTR_LEN(str) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, @@ -541,7 +545,7 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze return; } res = (v8js_script *)emalloc(sizeof(v8js_script)); - res->script = new v8::Persistent>(c->isolate, script.ToLocalChecked()); + res->script = new v8::Global(c->isolate, script.ToLocalChecked()); v8::String::Utf8Value _sname(isolate, sname); res->name = estrndup(ToCString(_sname), _sname.length()); diff --git a/v8js_class.h b/v8js_class.h index c69514d..cb89824 100644 --- a/v8js_class.h +++ b/v8js_class.h @@ -17,10 +17,10 @@ /* Abbreviate long type names */ -typedef v8::Persistent > v8js_function_tmpl_t; -typedef v8::Persistent > v8js_object_tmpl_t; -typedef v8::Persistent > v8js_persistent_obj_t; -typedef v8::Persistent > v8js_persistent_value_t; +typedef v8::Global v8js_function_tmpl_t; +typedef v8::Global v8js_object_tmpl_t; +typedef v8::Global v8js_persistent_obj_t; +typedef v8::Global v8js_persistent_value_t; /* Forward declarations */ struct v8js_v8object; @@ -35,8 +35,8 @@ struct cmp_str { /* {{{ Context container */ struct v8js_ctx { - v8::Persistent object_name; - v8::Persistent context; + v8::Global object_name; + v8::Global context; int in_execution; v8::Isolate *isolate; diff --git a/v8js_methods.cc b/v8js_methods.cc index 63a28db..78a78da 100644 --- a/v8js_methods.cc +++ b/v8js_methods.cc @@ -405,7 +405,7 @@ V8JS_METHOD(require) // If we have already loaded and cached this module then use it if (c->modules_loaded.count(normalised_module_id) > 0) { - v8::Persistent newobj; + v8::Global newobj; newobj.Reset(isolate, c->modules_loaded[normalised_module_id]); // TODO store v8::Global in c->modules_loaded directly!? @@ -502,7 +502,11 @@ V8JS_METHOD(require) // Set script identifier v8::Local sname = V8JS_STR(normalised_module_id); - v8::ScriptOrigin origin(isolate, sname); +#if PHP_V8_API_VERSION >= 12002000 + v8::ScriptOrigin origin(sname); +#else + v8::ScriptOrigin origin(c->isolate, sname); +#endif if (Z_STRLEN(module_code) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, diff --git a/v8js_object_export.cc b/v8js_object_export.cc index eca9ae8..2792058 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -648,12 +648,10 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) /* }}} */ /* This method handles named property and method get/set/query/delete. */ -template -v8::Local v8js_named_property_callback(v8::Local property_name, const v8::PropertyCallbackInfo &info, property_op_t callback_type, v8::Local set_value) /* {{{ */ +v8::Local v8js_named_property_callback(v8::Isolate *isolate, v8::Local self, v8::Local property_name, property_op_t callback_type, v8::Local set_value) /* {{{ */ { v8::Local property = v8::Local::Cast(property_name); - v8::Isolate *isolate = info.GetIsolate(); v8::Local v8_context = isolate->GetEnteredOrMicrotaskContext(); v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); v8::String::Utf8Value cstr(isolate, property); @@ -662,7 +660,6 @@ v8::Local v8js_named_property_callback(v8::Local property_n char *lower = estrndup(name, name_len); zend_string *method_name; - v8::Local self = info.Holder(); v8::Local ret_value; v8::Local cb; @@ -860,44 +857,62 @@ v8::Local v8js_named_property_callback(v8::Local property_n } /* }}} */ -static void v8js_named_property_getter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ +static V8JS_INTERCEPTED v8js_named_property_getter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ { - info.GetReturnValue().Set(v8js_named_property_callback(property, info, V8JS_PROP_GETTER)); -} -/* }}} */ + v8::Local r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_GETTER); -static void v8js_named_property_setter(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo &info) /* {{{ */ -{ - info.GetReturnValue().Set(v8js_named_property_callback(property, info, V8JS_PROP_SETTER, value)); -} -/* }}} */ - -static void v8js_named_property_query(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ -{ - v8::Local r = v8js_named_property_callback(property, info, V8JS_PROP_QUERY); if (r.IsEmpty()) { - return; + return V8JS_INTERCEPTED_NO; + } else { + info.GetReturnValue().Set(r); + return V8JS_INTERCEPTED_YES; + } +} +/* }}} */ + +static V8JS_INTERCEPTED v8js_named_property_setter(v8::Local property, v8::Local value, const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info) /* {{{ */ +{ + v8::Local r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_SETTER, value); +#if PHP_V8_HAS_INTERCEPTED + return r.IsEmpty() ? v8::Intercepted::kNo : v8::Intercepted::kYes; +#else + info.GetReturnValue().Set(r); +#endif +} +/* }}} */ + +static V8JS_INTERCEPTED v8js_named_property_query(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ +{ + v8::Local r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_QUERY); + if (r.IsEmpty()) { + return V8JS_INTERCEPTED_NO; } v8::Isolate *isolate = info.GetIsolate(); v8::MaybeLocal value = r->ToInteger(isolate->GetEnteredOrMicrotaskContext()); - if (!value.IsEmpty()) { + if (value.IsEmpty()) { + return V8JS_INTERCEPTED_NO; + } else { info.GetReturnValue().Set(value.ToLocalChecked()); + return V8JS_INTERCEPTED_YES; } } /* }}} */ -static void v8js_named_property_deleter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ +static V8JS_INTERCEPTED v8js_named_property_deleter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ { - v8::Local r = v8js_named_property_callback(property, info, V8JS_PROP_DELETER); + v8::Local r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_DELETER); if (r.IsEmpty()) { - return; + return V8JS_INTERCEPTED_NO; } v8::Isolate *isolate = info.GetIsolate(); v8::Local value = r->ToBoolean(isolate); - if (!value.IsEmpty()) { + if (value.IsEmpty()) { + return V8JS_INTERCEPTED_NO; + } else { info.GetReturnValue().Set(value); + return V8JS_INTERCEPTED_YES; } } /* }}} */ @@ -940,7 +955,11 @@ static v8::MaybeLocal v8js_wrap_object(v8::Isolate *isolate, zend_cl /* We'll free persist_tpl_ when template_cache is destroyed */ v8::Local inst_tpl = new_tpl->InstanceTemplate(); +#if PHP_V8_HAS_INTERCEPTED + v8::NamedPropertyGetterCallback getter = v8js_named_property_getter; +#else v8::GenericNamedPropertyGetterCallback getter = v8js_named_property_getter; +#endif v8::GenericNamedPropertyEnumeratorCallback enumerator = v8js_named_property_enumerator; /* Check for ArrayAccess object */ @@ -958,11 +977,12 @@ static v8::MaybeLocal v8js_wrap_object(v8::Isolate *isolate, zend_cl } if(has_array_access && has_countable) { - inst_tpl->SetIndexedPropertyHandler(v8js_array_access_getter, - v8js_array_access_setter, - v8js_array_access_query, - v8js_array_access_deleter, - v8js_array_access_enumerator); + inst_tpl->SetHandler( + v8::IndexedPropertyHandlerConfiguration(v8js_array_access_getter, + v8js_array_access_setter, + v8js_array_access_query, + v8js_array_access_deleter, + v8js_array_access_enumerator)); /* Switch to special ArrayAccess getter, which falls back to * v8js_named_property_getter, but possibly bridges the diff --git a/v8js_object_export.h b/v8js_object_export.h index d562541..8bd47aa 100644 --- a/v8js_object_export.h +++ b/v8js_object_export.h @@ -25,11 +25,9 @@ typedef enum { V8JS_PROP_DELETER } property_op_t; -template -v8::Local v8js_named_property_callback(v8::Local property, - const v8::PropertyCallbackInfo &info, - property_op_t callback_type, - v8::Local set_value = v8::Local()); +v8::Local v8js_named_property_callback(v8::Isolate *isolate, v8::Local self, + v8::Local property, property_op_t callback_type, + v8::Local set_value = v8::Local()); void v8js_php_callback(const v8::FunctionCallbackInfo& info); diff --git a/v8js_v8.h b/v8js_v8.h index 46e28a9..71235dc 100644 --- a/v8js_v8.h +++ b/v8js_v8.h @@ -113,6 +113,22 @@ int v8js_get_properties_hash(v8::Local jsValue, HashTable *retval, in #define IS_LONG 99 #endif +#define PHP_V8_HAS_INTERCEPTED PHP_V8_API_VERSION >= 12005000 + +#if PHP_V8_HAS_INTERCEPTED +#define V8JS_INTERCEPTED v8::Intercepted +#define V8JS_INTERCEPTED_YES v8::Intercepted::kYes +#define V8JS_INTERCEPTED_NO v8::Intercepted::kNo +#define V8JS_SETTER_PROPERTY_CALLBACK_INFO v8::PropertyCallbackInfo + +#else +#define V8JS_INTERCEPTED void +#define V8JS_INTERCEPTED_YES +#define V8JS_INTERCEPTED_NO +#define V8JS_SETTER_PROPERTY_CALLBACK_INFO v8::PropertyCallbackInfo + +#endif + #endif /* V8JS_V8_H */ diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index a27fd63..b0e8007 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -537,7 +537,7 @@ static zend_object *v8js_v8object_new(zend_class_entry *ce) /* {{{ */ zend_object_std_init(&c->std, ce); c->std.handlers = &v8js_v8object_handlers; - new (&c->v8obj) v8::Persistent(); + new (&c->v8obj) v8::Global(); return &c->std; } @@ -624,7 +624,7 @@ static zend_object *v8js_v8generator_new(zend_class_entry *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::Global(); return &c->v8obj.std; } diff --git a/v8js_v8object_class.h b/v8js_v8object_class.h index 0bb7ed0..f7c39a8 100644 --- a/v8js_v8object_class.h +++ b/v8js_v8object_class.h @@ -16,7 +16,7 @@ /* {{{ Object container */ struct v8js_v8object { - v8::Persistent v8obj; + v8::Global v8obj; int flags; struct v8js_ctx *ctx; HashTable *properties; diff --git a/v8js_variables.cc b/v8js_variables.cc index e64d122..5d52071 100644 --- a/v8js_variables.cc +++ b/v8js_variables.cc @@ -25,7 +25,7 @@ extern "C" { #include "zend_exceptions.h" } -static void v8js_fetch_php_variable(v8::Local name, const v8::PropertyCallbackInfo& info) /* {{{ */ +static void v8js_fetch_php_variable(v8::Local name, const v8::PropertyCallbackInfo& info) /* {{{ */ { v8::Local data = v8::Local::Cast(info.Data()); v8js_accessor_ctx *ctx = static_cast(data->Value()); @@ -80,7 +80,7 @@ void v8js_register_accessors(std::vector *accessor_list, v8: ctx->isolate = isolate; /* Set the variable fetch callback for given symbol on named property */ - php_obj->SetAccessor(V8JS_STRL(ZSTR_VAL(property_name), static_cast(ZSTR_LEN(property_name))), v8js_fetch_php_variable, NULL, v8::External::New(isolate, ctx)); + php_obj->SetNativeDataProperty(V8JS_STRL(ZSTR_VAL(property_name), static_cast(ZSTR_LEN(property_name))), v8js_fetch_php_variable, NULL, v8::External::New(isolate, ctx), v8::PropertyAttribute::ReadOnly); /* record the context so we can free it later */ accessor_list->push_back(ctx);