Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support v8 12.x, retaining compatibility with 10.2 #536

Merged
merged 3 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions v8js_array_access.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<v8::Value>& info) /* {{{ */
V8JS_INTERCEPTED v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
Expand All @@ -70,12 +70,17 @@ void v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo<v8:
v8::Local<v8::Value> 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<v8::Value> value,
const v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */
V8JS_INTERCEPTED v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
Expand All @@ -86,20 +91,22 @@ void v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
ZVAL_UNDEF(&zvalue);

if (v8js_to_zval(value, &zvalue, 0, isolate) != SUCCESS) {
info.GetReturnValue().Set(v8::Local<v8::Value>());
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;
}
/* }}} */

Expand Down Expand Up @@ -159,7 +166,7 @@ static void v8js_array_access_length(v8::Local<v8::String> property, const v8::P
}
/* }}} */

void v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) /* {{{ */
V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
Expand All @@ -173,10 +180,11 @@ void v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo<v8
zval_ptr_dtor(&php_value);

info.GetReturnValue().Set(V8JS_BOOL(true));
return V8JS_INTERCEPTED_YES;
}
/* }}} */

void v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) /* {{{ */
V8JS_INTERCEPTED v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
Expand All @@ -187,7 +195,10 @@ void v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo<v8::
* otherwise we're expected to return an empty handle. */
if(v8js_array_access_isset_p(object, index)) {
info.GetReturnValue().Set(V8JS_UINT(v8::PropertyAttribute::None));
return V8JS_INTERCEPTED_YES;
}

return V8JS_INTERCEPTED_NO;
}
/* }}} */

Expand Down Expand Up @@ -217,7 +228,7 @@ void v8js_array_access_enumerator(const v8::PropertyCallbackInfo<v8::Array>& inf



void v8js_array_access_named_getter(v8::Local<v8::Name> property_name, const v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */
V8JS_INTERCEPTED v8js_array_access_named_getter(v8::Local<v8::Name> property_name, const v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */
{
v8::Local<v8::String> property = v8::Local<v8::String>::Cast(property_name);
v8::Isolate *isolate = info.GetIsolate();
Expand All @@ -226,10 +237,10 @@ void v8js_array_access_named_getter(v8::Local<v8::Name> property_name, const v8:

if(strcmp(name, "length") == 0) {
v8js_array_access_length(property, info);
return;
return V8JS_INTERCEPTED_YES;
}

v8::Local<v8::Value> ret_value = v8js_named_property_callback(property, info, V8JS_PROP_GETTER);
v8::Local<v8::Value> ret_value = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_GETTER);

if(ret_value.IsEmpty()) {
v8::Local<v8::Array> arr = v8::Array::New(isolate);
Expand All @@ -250,6 +261,7 @@ void v8js_array_access_named_getter(v8::Local<v8::Name> property_name, const v8:
}

info.GetReturnValue().Set(ret_value);
return V8JS_INTERCEPTED_YES;
}
/* }}} */

Expand Down
12 changes: 6 additions & 6 deletions v8js_array_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
#define V8JS_ARRAY_ACCESS_H

/* Indexed Property Handlers */
void v8js_array_access_getter(uint32_t index,
const v8::PropertyCallbackInfo<v8::Value>& info);
void v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
V8JS_INTERCEPTED v8js_array_access_getter(uint32_t index,
const v8::PropertyCallbackInfo<v8::Value>& info);
V8JS_INTERCEPTED v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info);
void v8js_array_access_enumerator(const v8::PropertyCallbackInfo<v8::Array>& info);
void v8js_array_access_deleter(uint32_t index,
V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index,
const v8::PropertyCallbackInfo<v8::Boolean>& info);
void v8js_array_access_query(uint32_t index,
V8JS_INTERCEPTED v8js_array_access_query(uint32_t index,
const v8::PropertyCallbackInfo<v8::Integer>& info);

/* Named Property Handlers */
void v8js_array_access_named_getter(v8::Local<v8::Name> property,
V8JS_INTERCEPTED v8js_array_access_named_getter(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value> &info);

#endif /* V8JS_ARRAY_ACCESS_H */
Expand Down
26 changes: 15 additions & 11 deletions v8js_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extern const zend_function_entry v8js_methods[];
typedef struct _v8js_script {
char *name;
v8js_ctx *ctx;
v8::Persistent<v8::Script, v8::CopyablePersistentTraits<v8::Script>> *script;
v8::Global<v8::Script> *script;
} v8js_script;

static void v8js_script_free(v8js_script *res);
Expand Down Expand Up @@ -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<v8js_function_tmpl_t *, v8js_function_tmpl_t>::iterator it = c->call_impls.begin();
Expand Down Expand Up @@ -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<zend_object *, v8js_persistent_obj_t>::iterator it = c->weak_objects.begin();
Expand Down Expand Up @@ -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<v8::String>();
new(&c->context) v8::Persistent<v8::Context>();
new(&c->global_template) v8::Persistent<v8::FunctionTemplate>();
new(&c->array_tmpl) v8::Persistent<v8::FunctionTemplate>();
new(&c->object_name) v8::Global<v8::String>();
new(&c->context) v8::Global<v8::Context>();
new(&c->global_template) v8::Global<v8::FunctionTemplate>();
new(&c->array_tmpl) v8::Global<v8::FunctionTemplate>();

new(&c->modules_stack) std::vector<char*>();
new(&c->modules_loaded) std::map<char *, v8js_persistent_value_t, cmp_str>;
Expand Down Expand Up @@ -524,7 +524,11 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze
v8::Local<v8::String> 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<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
Expand All @@ -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<v8::Script, v8::CopyablePersistentTraits<v8::Script>>(c->isolate, script.ToLocalChecked());
res->script = new v8::Global<v8::Script>(c->isolate, script.ToLocalChecked());

v8::String::Utf8Value _sname(isolate, sname);
res->name = estrndup(ToCString(_sname), _sname.length());
Expand Down
12 changes: 6 additions & 6 deletions v8js_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@


/* Abbreviate long type names */
typedef v8::Persistent<v8::FunctionTemplate, v8::CopyablePersistentTraits<v8::FunctionTemplate> > v8js_function_tmpl_t;
typedef v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate> > v8js_object_tmpl_t;
typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> > v8js_persistent_obj_t;
typedef v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value> > v8js_persistent_value_t;
typedef v8::Global<v8::FunctionTemplate> v8js_function_tmpl_t;
typedef v8::Global<v8::ObjectTemplate> v8js_object_tmpl_t;
typedef v8::Global<v8::Object> v8js_persistent_obj_t;
typedef v8::Global<v8::Value> v8js_persistent_value_t;

/* Forward declarations */
struct v8js_v8object;
Expand All @@ -35,8 +35,8 @@ struct cmp_str {

/* {{{ Context container */
struct v8js_ctx {
v8::Persistent<v8::String> object_name;
v8::Persistent<v8::Context> context;
v8::Global<v8::String> object_name;
v8::Global<v8::Context> context;
int in_execution;
v8::Isolate *isolate;

Expand Down
8 changes: 6 additions & 2 deletions v8js_methods.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<v8::Value> newobj;
v8::Global<v8::Value> newobj;
newobj.Reset(isolate, c->modules_loaded[normalised_module_id]);

// TODO store v8::Global in c->modules_loaded directly!?
Expand Down Expand Up @@ -502,7 +502,11 @@ V8JS_METHOD(require)

// Set script identifier
v8::Local<v8::String> 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<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
Expand Down
62 changes: 41 additions & 21 deletions v8js_object_export.cc
Original file line number Diff line number Diff line change
Expand Up @@ -648,12 +648,10 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
/* }}} */

/* This method handles named property and method get/set/query/delete. */
template<typename T>
v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::Name> property_name, const v8::PropertyCallbackInfo<T> &info, property_op_t callback_type, v8::Local<v8::Value> set_value) /* {{{ */
v8::Local<v8::Value> v8js_named_property_callback(v8::Isolate *isolate, v8::Local<v8::Object> self, v8::Local<v8::Name> property_name, property_op_t callback_type, v8::Local<v8::Value> set_value) /* {{{ */
{
v8::Local<v8::String> property = v8::Local<v8::String>::Cast(property_name);

v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Context> v8_context = isolate->GetEnteredOrMicrotaskContext();
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
v8::String::Utf8Value cstr(isolate, property);
Expand All @@ -662,7 +660,6 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::Name> property_n
char *lower = estrndup(name, name_len);
zend_string *method_name;

v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Value> ret_value;
v8::Local<v8::Function> cb;

Expand Down Expand Up @@ -860,44 +857,62 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::Name> property_n
}
/* }}} */

static void v8js_named_property_getter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */
static V8JS_INTERCEPTED v8js_named_property_getter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */
{
info.GetReturnValue().Set(v8js_named_property_callback(property, info, V8JS_PROP_GETTER));
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_GETTER);

if (r.IsEmpty()) {
return V8JS_INTERCEPTED_NO;
} else {
info.GetReturnValue().Set(r);
return V8JS_INTERCEPTED_YES;
}
}
/* }}} */

static void v8js_named_property_setter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */
static V8JS_INTERCEPTED v8js_named_property_setter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info) /* {{{ */
{
info.GetReturnValue().Set(v8js_named_property_callback(property, info, V8JS_PROP_SETTER, value));
v8::Local<v8::Value> 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 void v8js_named_property_query(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Integer> &info) /* {{{ */
static V8JS_INTERCEPTED v8js_named_property_query(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Integer> &info) /* {{{ */
{
v8::Local<v8::Value> r = v8js_named_property_callback(property, info, V8JS_PROP_QUERY);
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_QUERY);
if (r.IsEmpty()) {
return;
return V8JS_INTERCEPTED_NO;
}

v8::Isolate *isolate = info.GetIsolate();
v8::MaybeLocal<v8::Integer> 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<v8::Name> property, const v8::PropertyCallbackInfo<v8::Boolean> &info) /* {{{ */
static V8JS_INTERCEPTED v8js_named_property_deleter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Boolean> &info) /* {{{ */
{
v8::Local<v8::Value> r = v8js_named_property_callback(property, info, V8JS_PROP_DELETER);
v8::Local<v8::Value> 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<v8::Boolean> value = r->ToBoolean(isolate);
if (!value.IsEmpty()) {
if (value.IsEmpty()) {
return V8JS_INTERCEPTED_NO;
} else {
info.GetReturnValue().Set(value);
return V8JS_INTERCEPTED_YES;
}
}
/* }}} */
Expand Down Expand Up @@ -940,7 +955,11 @@ static v8::MaybeLocal<v8::Object> v8js_wrap_object(v8::Isolate *isolate, zend_cl
/* We'll free persist_tpl_ when template_cache is destroyed */

v8::Local<v8::ObjectTemplate> 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 */
Expand All @@ -958,11 +977,12 @@ static v8::MaybeLocal<v8::Object> 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
Expand Down
Loading