From 59c2aaad9826ef05d5012924d068d78c9adbc7fc Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 21 Jul 2018 03:03:40 +0200 Subject: [PATCH 01/13] Replace obsolete AC_TRY_FOO with AC_FOO_IFELSE Autoconf made several macros obsolete including the AC_TRY_RUN in 2000 and since Autoconf 2.50: http://git.savannah.gnu.org/cgit/autoconf.git/tree/ChangeLog.2 These macros should be replaced with the current AC_FOO_IFELSE instead. It is fairly safe to upgrade and take the recommendation advice of autoconf upgrade manual since the upgrade should be compatible at least with PHP versions 5.4 and up, on some systems even with PHP 5.3. PHP versions from 5.4 to 7.1 require Autoconf 2.59+ and PHP 7.2+ require Autoconf 2.64+. This patch was created with the help of the autoupdate script: autoupdate config.m4 Reference docs: - https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Obsolete-Macros.html - https://www.gnu.org/software/autoconf/manual/autoconf-2.59/autoconf.pdf --- config.m4 | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/config.m4 b/config.m4 index fab921c..506e7ca 100644 --- a/config.m4 +++ b/config.m4 @@ -43,7 +43,7 @@ if test "$PHP_V8JS" != "no"; then old_CPPFLAGS=$CPPFLAGS AC_LANG_PUSH([C++]) CPPFLAGS="-std="$ac_cv_v8_cstd - AC_TRY_RUN([int main() { return 0; }],[],[ac_cv_v8_cstd="c++0x"],[]) + AC_RUN_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])],[],[ac_cv_v8_cstd="c++0x"],[]) AC_LANG_POP([C++]) CPPFLAGS=$old_CPPFLAGS ]); @@ -53,27 +53,27 @@ if test "$PHP_V8JS" != "no"; then old_CXXFLAGS=$CXXFLAGS AC_LANG_PUSH([C++]) CXXFLAGS="-std="$ac_cv_v8_cstd - AC_TRY_RUN([int main() { + AC_RUN_IFELSE([AC_LANG_SOURCE([[int main() { struct { unsigned int x; } foo = {-1}; (void) foo; return 0; - }], [ ac_cv_v8_narrowing="" ], [ + }]])],[ac_cv_v8_narrowing=""],[ CXXFLAGS="-Wno-c++11-narrowing -std="$ac_cv_v8_cstd - AC_TRY_RUN([int main() { + AC_RUN_IFELSE([AC_LANG_SOURCE([[int main() { struct { unsigned int x; } foo = {-1}; (void) foo; return 0; - }], [ ac_cv_v8_narrowing="-Wno-c++11-narrowing" ], [ + }]])],[ac_cv_v8_narrowing="-Wno-c++11-narrowing"],[ CXXFLAGS="-Wno-narrowing -std="$ac_cv_v8_cstd - AC_TRY_RUN([int main() { + AC_RUN_IFELSE([AC_LANG_SOURCE([[int main() { struct { unsigned int x; } foo = {-1}; (void) foo; return 0; - }], [ ac_cv_v8_narrowing="-Wno-narrowing" ], [ + }]])],[ac_cv_v8_narrowing="-Wno-narrowing"],[ AC_MSG_ERROR([cannot compile with narrowing]) - ], []) - ], []) - ], []) + ],[]) + ],[]) + ],[]) AC_LANG_POP([C++]) CXXFLAGS=$old_CXXFLAGS ]); @@ -117,7 +117,7 @@ if test "$PHP_V8JS" != "no"; then dnl LIBS="$LIBS $V8JS_SHARED_LIBADD" AC_CACHE_CHECK(for V8 version, ac_cv_v8_version, [ -AC_TRY_RUN([#include +AC_RUN_IFELSE([AC_LANG_SOURCE([[#include #include #include using namespace std; @@ -132,7 +132,7 @@ int main () return 0; } return 1; -}], [ac_cv_v8_version=`cat ./conftestval|awk '{print $1}'`], [ac_cv_v8_version=NONE], [ac_cv_v8_version=NONE]) +}]])],[ac_cv_v8_version=`cat ./conftestval|awk '{print $1}'`],[ac_cv_v8_version=NONE],[ac_cv_v8_version=NONE]) ]) if test "$ac_cv_v8_version" != "NONE"; then From 3327f2e3591114922f0b389efad49af3294bf221 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 21 Jul 2018 03:19:07 +0200 Subject: [PATCH 02/13] Add configure.ac to .gitignore If the phpize script is part of the PHP 7.0 or 7.1 installation there will be generated configure.in file from the PHP source code as a part of the old autotools files. If the phpize script is from PHP 7.2 or above there will be a new configure.ac file generated. This file is further used to generate the configure script. Having these files gitignored is useful when developing the extension. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2671f03..6e46a23 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ config.status config.sub configure configure.in +configure.ac *~ install-sh libtool From 06234e56c3ba92b82cfad069ea4f44f5dde35d2c Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 21 Jul 2018 04:48:23 +0200 Subject: [PATCH 03/13] Replace AC_LANG_SAVE, AC_LANG_CPLUSPLUS and AC_LANG_RESTORE Autoconf 2.50 in 2001 made several macros obsolete. These include also macros for temporary changing the language. Instead of these the AC_LANG_PUSH and AC_LANG_POP macros should be used with later Autoconf versions. Since PHP 5.4 to 7.1 require to have Autoconf 2.59+ and PHP 7.2 and later require Autoconf 2.64+ the upgrade is fairly safe and most systems should already be supported. Refs: - http://git.savannah.gnu.org/cgit/autoconf.git/tree/NEWS - https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Language-Choice.html --- config.m4 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index fab921c..d6d4237 100644 --- a/config.m4 +++ b/config.m4 @@ -83,8 +83,7 @@ if test "$PHP_V8JS" != "no"; then old_LDFLAGS=$LDFLAGS old_CPPFLAGS=$CPPFLAGS - AC_LANG_SAVE - AC_LANG_CPLUSPLUS + AC_LANG_PUSH([C++]) CPPFLAGS="$CPPFLAGS -I$V8_DIR/include -std=$ac_cv_v8_cstd" LDFLAGS="$LDFLAGS -L$V8_DIR/$PHP_LIBDIR" @@ -197,7 +196,7 @@ int main () [Define unless v8::ArrayBuffer::Allocator::NewDefaultAllocator is usable.]) fi - AC_LANG_RESTORE + AC_LANG_POP([C++]) LIBS=$old_LIBS LDFLAGS="$old_LDFLAGS" CPPFLAGS=$old_CPPFLAGS From ab6e2267afefa8f4e0c34c6be115acc14c5cad1d Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Wed, 12 Sep 2018 15:43:40 +0200 Subject: [PATCH 04/13] adapt mandatory api changes for V8 7.0.276.3, refs #374 --- php_v8js_macros.h | 4 -- v8js_array_access.cc | 9 ++-- v8js_array_access.h | 2 +- v8js_class.cc | 45 ++++++++++++++++---- v8js_convert.cc | 28 +++++++++---- v8js_exceptions.cc | 47 ++++++++++++--------- v8js_generator_export.cc | 11 +++-- v8js_methods.cc | 89 +++++++++++++++++++++++++++++----------- v8js_object_export.cc | 82 +++++++++++++++++++++++++----------- v8js_object_export.h | 2 +- v8js_v8.cc | 25 ++++++----- v8js_v8.h | 2 +- v8js_v8object_class.cc | 31 +++++++------- 13 files changed, 254 insertions(+), 123 deletions(-) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index 2503663..903a6d6 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -65,10 +65,6 @@ extern "C" { /* V8Js Version */ #define PHP_V8JS_VERSION "2.1.0" -/* Helper macros */ -#define V8JS_GET_CLASS_NAME(var, obj) \ - v8::String::Utf8Value var(obj->GetConstructorName()); - /* Options */ #define V8JS_FLAG_NONE (1<<0) #define V8JS_FLAG_FORCE_ARRAY (1<<1) diff --git a/v8js_array_access.cc b/v8js_array_access.cc index cabba33..bf7289a 100644 --- a/v8js_array_access.cc +++ b/v8js_array_access.cc @@ -221,9 +221,11 @@ void v8js_array_access_enumerator(const v8::PropertyCallbackInfo& inf -void v8js_array_access_named_getter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ +void v8js_array_access_named_getter(v8::Local property_name, const v8::PropertyCallbackInfo &info) /* {{{ */ { - v8::String::Utf8Value cstr(property); + v8::Local property = v8::Local::Cast(property_name); + v8::Isolate *isolate = info.GetIsolate(); + v8::String::Utf8Value cstr(isolate, property); const char *name = ToCString(cstr); if(strcmp(name, "length") == 0) { @@ -234,7 +236,6 @@ void v8js_array_access_named_getter(v8::Local property, const v8::Pr v8::Local ret_value = v8js_named_property_callback(property, info, V8JS_PROP_GETTER); if(ret_value.IsEmpty()) { - v8::Isolate *isolate = info.GetIsolate(); v8::Local arr = v8::Array::New(isolate); v8::Local prototype = arr->GetPrototype(); @@ -243,7 +244,7 @@ void v8js_array_access_named_getter(v8::Local property, const v8::Pr info.GetReturnValue().Set(ret_value); } - ret_value = prototype->ToObject()->Get(property); + ret_value = prototype->ToObject(isolate)->Get(property); } info.GetReturnValue().Set(ret_value); diff --git a/v8js_array_access.h b/v8js_array_access.h index ef5416a..283e1cb 100644 --- a/v8js_array_access.h +++ b/v8js_array_access.h @@ -25,7 +25,7 @@ void v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo& info); /* Named Property Handlers */ -void v8js_array_access_named_getter(v8::Local property, +void 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 9f67992..8430348 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -648,8 +648,8 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze v8::Local sname = identifier ? v8::String::NewFromUtf8(isolate, ZSTR_VAL(identifier), v8::String::kNormalString, static_cast(ZSTR_LEN(identifier))) : V8JS_SYM("V8Js::compileString()"); + v8::ScriptOrigin origin(sname); - /* Compiles a string context independently. TODO: Add a php function which calls this and returns the result as resource which can be executed later. */ if (ZSTR_LEN(str) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, "Script source exceeds maximum supported length", 0); @@ -657,7 +657,7 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze } v8::Local source = v8::String::NewFromUtf8(isolate, ZSTR_VAL(str), v8::String::kNormalString, static_cast(ZSTR_LEN(str))); - v8::Local script = v8::Script::Compile(source, sname); + v8::MaybeLocal script = v8::Script::Compile(v8::Local::New(isolate, c->context), source, &origin); /* Compile errors? */ if (script.IsEmpty()) { @@ -665,9 +665,9 @@ 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); + res->script = new v8::Persistent>(c->isolate, script.ToLocalChecked()); - v8::String::Utf8Value _sname(sname); + v8::String::Utf8Value _sname(isolate, sname); res->name = estrndup(ToCString(_sname), _sname.length()); res->ctx = c; *ret = res; @@ -695,9 +695,9 @@ static void v8js_execute_script(zval *this_ptr, v8js_script *res, long flags, lo /* std::function relies on its dtor to be executed, otherwise it leaks * some memory on bailout. */ { - std::function< v8::Local(v8::Isolate *) > v8_call = [res](v8::Isolate *isolate) { + std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [c, res](v8::Isolate *isolate) { v8::Local script = v8::Local::New(isolate, *res->script); - return script->Run(); + return script->Run(v8::Local::New(isolate, c->context)); }; v8js_v8_call(c, return_value, flags, time_limit, memory_limit, v8_call); @@ -1153,6 +1153,31 @@ static PHP_METHOD(V8Js, getExtensions) } /* }}} */ +static v8::StartupData createSnapshotDataBlob(v8::SnapshotCreator *snapshot_creator, zend_string *str) /* {{{ */ +{ + v8::Isolate *isolate = snapshot_creator->GetIsolate(); + + { + v8::HandleScope scope(isolate); + v8::Local context = v8::Context::New(isolate); + + v8::Context::Scope context_scope(context); + v8::TryCatch try_catch(isolate); + + v8::Local source = v8::String::NewFromUtf8(isolate, ZSTR_VAL(str), v8::String::kNormalString, static_cast(ZSTR_LEN(str))); + v8::MaybeLocal script = v8::Script::Compile(context, source); + + if (script.IsEmpty() || script.ToLocalChecked()->Run(context).IsEmpty()) + { + return {nullptr, 0}; + } + + snapshot_creator->SetDefaultContext(context); + } + + return snapshot_creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); +} /* }}} */ + /* {{{ proto string|bool V8Js::createSnapshot(string embed_source) */ @@ -1172,7 +1197,9 @@ static PHP_METHOD(V8Js, createSnapshot) /* Initialize V8, if not already done. */ v8js_v8_init(); - v8::StartupData snapshot_blob = v8::V8::CreateSnapshotDataBlob(ZSTR_VAL(script)); + v8::Isolate *isolate = v8::Isolate::Allocate(); + v8::SnapshotCreator snapshot_creator(isolate); + v8::StartupData snapshot_blob = createSnapshotDataBlob(&snapshot_creator, script); if (!snapshot_blob.data) { php_error_docref(NULL, E_WARNING, "Failed to create V8 heap snapshot. Check $embed_source for errors."); @@ -1303,7 +1330,7 @@ static void v8js_write_property(zval *object, zval *member, zval *value, void ** (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(object_name_js)->ToObject(); + v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(object_name_js)->ToObject(isolate); if (Z_STRLEN_P(member) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, @@ -1327,7 +1354,7 @@ static void v8js_unset_property(zval *object, zval *member, void **cache_slot) / /* Global PHP JS object */ v8::Local object_name_js = v8::Local::New(isolate, c->object_name); - v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(object_name_js)->ToObject(); + v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(object_name_js)->ToObject(isolate); if (Z_STRLEN_P(member) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, diff --git a/v8js_convert.cc b/v8js_convert.cc index 3f91dd1..3271685 100644 --- a/v8js_convert.cc +++ b/v8js_convert.cc @@ -200,27 +200,41 @@ v8::Local zval_to_v8js(zval *value, v8::Isolate *isolate) /* {{{ */ int v8js_to_zval(v8::Local jsValue, zval *return_value, int flags, v8::Isolate *isolate) /* {{{ */ { + v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + if (jsValue->IsString()) { - v8::String::Utf8Value str(jsValue); + v8::String::Utf8Value str(isolate, jsValue); const char *cstr = ToCString(str); - RETVAL_STRINGL(cstr, jsValue->ToString()->Utf8Length()); + RETVAL_STRINGL(cstr, jsValue->ToString(isolate)->Utf8Length(isolate)); } else if (jsValue->IsBoolean()) { - RETVAL_BOOL(jsValue->Uint32Value()); + v8::Maybe value = jsValue->BooleanValue(v8::Local::New(isolate, ctx->context)); + if (value.IsNothing()) { + return FAILURE; + } + RETVAL_BOOL(value.ToChecked()); } else if (jsValue->IsInt32() || jsValue->IsUint32()) { - RETVAL_LONG((long) jsValue->IntegerValue()); + v8::Maybe value = jsValue->IntegerValue(v8::Local::New(isolate, ctx->context)); + if (value.IsNothing()) { + return FAILURE; + } + RETVAL_LONG((long) value.ToChecked()); } else if (jsValue->IsNumber()) { - RETVAL_DOUBLE(jsValue->NumberValue()); + v8::Maybe value = jsValue->NumberValue(v8::Local::New(isolate, ctx->context)); + if (value.IsNothing()) { + return FAILURE; + } + RETVAL_DOUBLE(value.ToChecked()); } else if (jsValue->IsDate()) /* Return as a PHP DateTime object */ { - v8::String::Utf8Value str(jsValue); + v8::String::Utf8Value str(isolate, jsValue); const char *cstr = ToCString(str); /* cstr has two timezone specifications: @@ -253,7 +267,7 @@ int v8js_to_zval(v8::Local jsValue, zval *return_value, int flags, v8 } else if (jsValue->IsObject()) { - v8::Local self = jsValue->ToObject(); + v8::Local self = jsValue->ToObject(isolate); // if this is a wrapped PHP object, then just unwrap it. if (self->InternalFieldCount() == 2) { diff --git a/v8js_exceptions.cc b/v8js_exceptions.cc index 967cae8..2947198 100644 --- a/v8js_exceptions.cc +++ b/v8js_exceptions.cc @@ -39,12 +39,14 @@ zend_class_entry *php_ce_v8js_memory_limit_exception; void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8::TryCatch *try_catch) /* {{{ */ { - v8::String::Utf8Value exception(try_catch->Exception()); + v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local context = v8::Local::New(isolate, ctx->context); + + v8::String::Utf8Value exception(isolate, try_catch->Exception()); const char *exception_string = ToCString(exception); v8::Local tc_message = try_catch->Message(); const char *filename_string, *sourceline_string; char *message_string; - int linenum, start_col; object_init_ex(return_value, php_ce_v8js_script_exception); @@ -56,35 +58,42 @@ void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8:: } else { - v8::String::Utf8Value filename(tc_message->GetScriptResourceName()); + v8::String::Utf8Value filename(isolate, tc_message->GetScriptResourceName()); filename_string = ToCString(filename); PHPV8_EXPROP(_string, JsFileName, filename_string); - v8::String::Utf8Value sourceline(tc_message->GetSourceLine()); - sourceline_string = ToCString(sourceline); - PHPV8_EXPROP(_string, JsSourceLine, sourceline_string); + v8::MaybeLocal maybe_sourceline = tc_message->GetSourceLine(context); + if (!maybe_sourceline.IsEmpty()) { + v8::String::Utf8Value sourceline(isolate, maybe_sourceline.ToLocalChecked()); + sourceline_string = ToCString(sourceline); + PHPV8_EXPROP(_string, JsSourceLine, sourceline_string); + } - linenum = tc_message->GetLineNumber(); - PHPV8_EXPROP(_long, JsLineNumber, linenum); + v8::Maybe linenum = tc_message->GetLineNumber(context); + if (linenum.IsJust()) { + PHPV8_EXPROP(_long, JsLineNumber, linenum.FromJust()); + } - start_col = tc_message->GetStartColumn(); - PHPV8_EXPROP(_long, JsStartColumn, start_col); + v8::Maybe start_col = tc_message->GetStartColumn(context); + if (start_col.IsJust()) { + PHPV8_EXPROP(_long, JsStartColumn, start_col.FromJust()); + } - v8::Maybe end_col = tc_message->GetEndColumn(isolate->GetEnteredContext()); + v8::Maybe end_col = tc_message->GetEndColumn(context); if (end_col.IsJust()) { PHPV8_EXPROP(_long, JsEndColumn, end_col.FromJust()); } - spprintf(&message_string, 0, "%s:%d: %s", filename_string, linenum, exception_string); + spprintf(&message_string, 0, "%s:%d: %s", filename_string, linenum.FromMaybe(0), exception_string); - v8::String::Utf8Value stacktrace(try_catch->StackTrace()); - if (stacktrace.length() > 0) { - const char* stacktrace_string = ToCString(stacktrace); - PHPV8_EXPROP(_string, JsTrace, stacktrace_string); + v8::MaybeLocal maybe_stacktrace = try_catch->StackTrace(context); + if (!maybe_stacktrace.IsEmpty()) { + v8::String::Utf8Value stacktrace(isolate, maybe_stacktrace.ToLocalChecked()); + PHPV8_EXPROP(_string, JsTrace, ToCString(stacktrace)); } - if(try_catch->Exception()->IsObject() && try_catch->Exception()->ToObject()->InternalFieldCount() == 2) { - zend_object *php_exception = reinterpret_cast(try_catch->Exception()->ToObject()->GetAlignedPointerFromInternalField(1)); + if(try_catch->Exception()->IsObject() && try_catch->Exception()->ToObject(isolate)->InternalFieldCount() == 2) { + zend_object *php_exception = reinterpret_cast(try_catch->Exception()->ToObject(isolate)->GetAlignedPointerFromInternalField(1)); zend_class_entry *exception_ce = zend_exception_get_default(); if (instanceof_function(php_exception->ce, exception_ce)) { @@ -106,7 +115,7 @@ void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8:: void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch) /* {{{ */ { - v8::String::Utf8Value exception(try_catch->Exception()); + v8::String::Utf8Value exception(isolate, try_catch->Exception()); const char *exception_string = ToCString(exception); zval zexception; diff --git a/v8js_generator_export.cc b/v8js_generator_export.cc index a27fa93..2d5f1ce 100644 --- a/v8js_generator_export.cc +++ b/v8js_generator_export.cc @@ -24,6 +24,9 @@ v8::Local v8js_wrap_generator(v8::Isolate *isolate, v8::LocalIsObject()); + v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local context = v8::Local::New(isolate, ctx->context); + v8::TryCatch try_catch(isolate); v8::Local source = v8::String::NewFromUtf8(isolate, "(\ function(wrapped_object) { \ @@ -37,21 +40,21 @@ function(wrapped_object) { \ } \ })(); \ })"); - v8::Local script = v8::Script::Compile(source); + v8::MaybeLocal script = v8::Script::Compile(context, source); if(script.IsEmpty()) { zend_error(E_ERROR, "Failed to compile Generator object wrapper"); return result; } - v8::Local wrapper_fn_val = script->Run(); + v8::MaybeLocal wrapper_fn_val = script.ToLocalChecked()->Run(context); - if(wrapper_fn_val.IsEmpty() || !wrapper_fn_val->IsFunction()) { + if(wrapper_fn_val.IsEmpty() || !wrapper_fn_val.ToLocalChecked()->IsFunction()) { zend_error(E_ERROR, "Failed to create Generator object wrapper function"); return result; } - v8::Local wrapper_fn = v8::Local::Cast(wrapper_fn_val); + v8::Local wrapper_fn = v8::Local::Cast(wrapper_fn_val.ToLocalChecked()); v8::Local *jsArgv = static_cast *>(alloca(sizeof(v8::Local))); new(&jsArgv[0]) v8::Local; diff --git a/v8js_methods.cc b/v8js_methods.cc index 4bee095..cd761bd 100644 --- a/v8js_methods.cc +++ b/v8js_methods.cc @@ -35,7 +35,14 @@ V8JS_METHOD(exit) /* {{{ */ /* global.sleep - sleep for passed seconds */ V8JS_METHOD(sleep) /* {{{ */ { - php_sleep(info[0]->Int32Value()); + v8::Isolate *isolate = info.GetIsolate(); + v8js_ctx *c = (v8js_ctx *) isolate->GetData(0); + + v8::Maybe t = info[0]->Int32Value(v8::Local::New(isolate, c->context)); + + if (t.IsJust()) { + php_sleep(t.FromJust()); + } } /* }}} */ @@ -46,7 +53,7 @@ V8JS_METHOD(print) /* {{{ */ zend_long ret = 0; for (int i = 0; i < info.Length(); i++) { - v8::String::Utf8Value str(info[i]); + v8::String::Utf8Value str(isolate, info[i]); const char *cstr = ToCString(str); ret = PHPWRITE(cstr, strlen(cstr)); } @@ -57,6 +64,9 @@ V8JS_METHOD(print) /* {{{ */ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int level) /* {{{ */ { + v8js_ctx *c = (v8js_ctx *) isolate->GetData(0); + v8::Local context = v8::Local::New(isolate, c->context); + if (level > 1) { php_printf("%*c", (level - 1) * 2, ' '); } @@ -73,22 +83,54 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve } if (var->IsInt32()) { - php_printf("int(%ld)\n", (long) var->IntegerValue()); + v8::Maybe value = var->IntegerValue(context); + if (value.IsNothing()) + { + php_printf("\n"); + } + else + { + php_printf("int(%ld)\n", (long) value.FromJust()); + } return; } if (var->IsUint32()) { - php_printf("int(%lu)\n", (unsigned long) var->IntegerValue()); + v8::Maybe value = var->Uint32Value(context); + if (value.IsNothing()) + { + php_printf("\n"); + } + else + { + php_printf("int(%lu)\n", (unsigned long) value.FromJust()); + } return; } if (var->IsNumber()) { - php_printf("float(%f)\n", var->NumberValue()); + v8::Maybe value = var->NumberValue(context); + if (value.IsNothing()) + { + php_printf("\n"); + } + else + { + php_printf("float(%f)\n", value.FromJust()); + } return; } if (var->IsBoolean()) { - php_printf("bool(%s)\n", var->BooleanValue() ? "true" : "false"); + v8::Maybe value = var->BooleanValue(context); + if (value.IsNothing()) + { + php_printf("\n"); + } + else + { + php_printf("bool(%s)\n", value.FromJust() ? "true" : "false"); + } return; } @@ -100,16 +142,16 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve details = re->GetSource(); } else { - details = var->ToDetailString(isolate->GetEnteredContext()).FromMaybe(v8::Local()); + details = var->ToDetailString(context).FromMaybe(v8::Local()); if (try_catch.HasCaught()) { details = V8JS_SYM(""); } } - v8::String::Utf8Value str(details); + v8::String::Utf8Value str(isolate, details); const char *valstr = ToCString(str); - size_t valstr_len = details->ToString()->Utf8Length(); + size_t valstr_len = details->ToString(isolate)->Utf8Length(isolate); if (var->IsString()) { @@ -147,12 +189,12 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve else if (var->IsObject()) { v8::Local object = v8::Local::Cast(var); - V8JS_GET_CLASS_NAME(cname, object); + v8::String::Utf8Value cname(isolate, object->GetConstructorName()); int hash = object->GetIdentityHash(); if (var->IsFunction() && strcmp(ToCString(cname), "Closure") != 0) { - v8::String::Utf8Value csource(object->ToString()); + v8::String::Utf8Value csource(isolate, object->ToString(isolate)); php_printf("object(Closure)#%d {\n%*c%s\n", hash, level * 2 + 2, ' ', ToCString(csource)); } else @@ -169,8 +211,8 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve php_printf(" (%d) {\n", length); for (unsigned i = 0; i < length; i++) { - v8::Local key = keys->Get(i)->ToString(); - v8::String::Utf8Value kname(key); + v8::Local key = keys->Get(i)->ToString(isolate); + v8::String::Utf8Value kname(isolate, key); php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(kname)); v8js_dumper(isolate, object->Get(key), level + 1); } @@ -207,7 +249,7 @@ V8JS_METHOD(require) v8::Isolate *isolate = info.GetIsolate(); v8js_ctx *c = (v8js_ctx *) isolate->GetData(0); - v8::String::Utf8Value module_base(info.Data()); + v8::String::Utf8Value module_base(isolate, info.Data()); const char *module_base_cstr = ToCString(module_base); // Check that we have a module loader @@ -216,7 +258,7 @@ V8JS_METHOD(require) return; } - v8::String::Utf8Value module_id_v8(info[0]); + v8::String::Utf8Value module_id_v8(isolate, info[0]); const char *module_id = ToCString(module_id_v8); char *normalised_path, *module_name; @@ -407,7 +449,7 @@ V8JS_METHOD(require) } if(Z_TYPE(module_code) == IS_OBJECT) { - v8::Local newobj = zval_to_v8js(&module_code, isolate)->ToObject(); + v8::Local newobj = zval_to_v8js(&module_code, isolate)->ToObject(isolate); c->modules_loaded[normalised_module_id].Reset(isolate, newobj); info.GetReturnValue().Set(newobj); @@ -435,6 +477,7 @@ V8JS_METHOD(require) // Set script identifier v8::Local sname = V8JS_STR(normalised_module_id); + v8::ScriptOrigin origin(sname); if (Z_STRLEN(module_code) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, @@ -445,11 +488,11 @@ V8JS_METHOD(require) v8::Local source = V8JS_ZSTR(Z_STR(module_code)); zval_ptr_dtor(&module_code); - source = v8::String::Concat(V8JS_SYM("(function (exports, module, require) {"), source); - source = v8::String::Concat(source, V8JS_SYM("\n});")); + source = v8::String::Concat(isolate, V8JS_SYM("(function (exports, module, require) {"), source); + source = v8::String::Concat(isolate, source, V8JS_SYM("\n});")); // Create and compile script - v8::Local script = v8::Script::Compile(source, sname); + v8::MaybeLocal script = v8::Script::Compile(context, source, &origin); // The script will be empty if there are compile errors if (script.IsEmpty()) { @@ -474,7 +517,7 @@ V8JS_METHOD(require) c->modules_stack.push_back(normalised_module_id); // Run script to evaluate closure - v8::Local module_function = script->Run(); + v8::MaybeLocal module_function = script.ToLocalChecked()->Run(context); // Prepare exports & module object v8::Local exports = v8::Object::New(isolate); @@ -483,7 +526,7 @@ V8JS_METHOD(require) module->Set(V8JS_SYM("id"), V8JS_STR(normalised_module_id)); module->Set(V8JS_SYM("exports"), exports); - if (module_function->IsFunction()) { + if (!module_function.IsEmpty() && module_function.ToLocalChecked()->IsFunction()) { v8::Local *jsArgv = static_cast *>(alloca(3 * sizeof(v8::Local))); new(&jsArgv[0]) v8::Local; jsArgv[0] = exports; @@ -495,7 +538,7 @@ V8JS_METHOD(require) jsArgv[2] = require_fn.ToLocalChecked(); // actually call the module - v8::Local::Cast(module_function)->Call(exports, 3, jsArgv); + v8::Local::Cast(module_function.ToLocalChecked())->Call(exports, 3, jsArgv); } // Remove this module and path from the stack @@ -503,7 +546,7 @@ V8JS_METHOD(require) efree(normalised_path); - if (!module_function->IsFunction()) { + if (module_function.IsEmpty() || !module_function.ToLocalChecked()->IsFunction()) { info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Wrapped module script failed to return function"))); efree(normalised_module_id); return; diff --git a/v8js_object_export.cc b/v8js_object_export.cc index 3568871..6a01009 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -100,9 +100,9 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v if (argc) { fci.params = (zval *) safe_emalloc(argc, sizeof(zval), 0); for (i = 0; i < argc; i++) { - if (info[i]->IsObject() && info[i]->ToObject()->InternalFieldCount() == 2) { + if (info[i]->IsObject() && info[i]->ToObject(isolate)->InternalFieldCount() == 2) { /* This is a PHP object, passed to JS and back. */ - zend_object *object = reinterpret_cast(info[i]->ToObject()->GetAlignedPointerFromInternalField(1)); + zend_object *object = reinterpret_cast(info[i]->ToObject(isolate)->GetAlignedPointerFromInternalField(1)); ZVAL_OBJ(&fci.params[i], object); Z_ADDREF_P(&fci.params[i]); } else { @@ -404,7 +404,7 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfoSet(result_len++, V8JS_FLOAT((double) index)->ToString()); + result->Set(result_len++, V8JS_FLOAT((double) index)->ToString(isolate)); } } ZEND_HASH_FOREACH_END(); @@ -430,9 +430,9 @@ static void v8js_invoke_callback(const v8::FunctionCallbackInfo& info if (info.IsConstructCall()) { v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); - v8::Local str = self->GetConstructorName()->ToString(); - v8::String::Utf8Value str_value(str); - zend_string *constructor_name = zend_string_init(ToCString(str_value), str->Utf8Length(), 0); + v8::MaybeLocal str = self->GetConstructorName()->ToString(isolate); + v8::String::Utf8Value str_value(isolate, str.ToLocalChecked()); + zend_string *constructor_name = zend_string_init(ToCString(str_value), str.ToLocalChecked()->Utf8Length(isolate), 0); zend_class_entry *ce = zend_lookup_class(constructor_name); zend_string_release(constructor_name); @@ -529,10 +529,30 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) return; } - v8::Local str = info[0]->ToString(); - v8::String::Utf8Value str_value(str); + v8::MaybeLocal str = info[0]->ToString(isolate); + + if (str.IsEmpty()) + { + error_len = spprintf(&error, 0, + "%s::__call expect 1st parameter to be valid function name, toString() invocation failed.", + ce->name); + + if (error_len > std::numeric_limits::max()) { + zend_throw_exception(php_ce_v8js_exception, + "Generated error message length exceeds maximum supported length", 0); + } + else { + return_value = V8JS_THROW(isolate, TypeError, error, static_cast(error_len)); + } + + efree(error); + info.GetReturnValue().Set(return_value); + return; + } + + v8::String::Utf8Value str_value(isolate, str.ToLocalChecked()); const char *method_c_name = ToCString(str_value); - zend_string *method_name = zend_string_init(method_c_name, str->Utf8Length(), 0); + zend_string *method_name = zend_string_init(method_c_name, str.ToLocalChecked()->Utf8Length(isolate), 0); // okay, look up the method name and manually invoke it. const zend_object_handlers *h = object->handlers; @@ -577,13 +597,15 @@ 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, const v8::PropertyCallbackInfo &info, property_op_t callback_type, v8::Local set_value) /* {{{ */ +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 property = v8::Local::Cast(property_name); + v8::Isolate *isolate = info.GetIsolate(); v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); - v8::String::Utf8Value cstr(property); + v8::String::Utf8Value cstr(isolate, property); const char *name = ToCString(cstr); - uint name_len = property->Utf8Length(); + uint name_len = property->Utf8Length(isolate); char *lower = estrndup(name, name_len); zend_string *method_name; @@ -780,32 +802,44 @@ v8::Local v8js_named_property_callback(v8::Local property } /* }}} */ -static void v8js_named_property_getter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ +static void v8js_named_property_getter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ { info.GetReturnValue().Set(v8js_named_property_callback(property, info, V8JS_PROP_GETTER)); } /* }}} */ -static void v8js_named_property_setter(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo &info) /* {{{ */ +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) /* {{{ */ +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()) { - info.GetReturnValue().Set(r->ToInteger()); + if (r.IsEmpty()) { + return; + } + + v8::Isolate *isolate = info.GetIsolate(); + v8::MaybeLocal value = r->ToInteger(isolate->GetEnteredContext()); + if (!value.IsEmpty()) { + info.GetReturnValue().Set(value.ToLocalChecked()); } } /* }}} */ -static void v8js_named_property_deleter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ +static void v8js_named_property_deleter(v8::Local property, const v8::PropertyCallbackInfo &info) /* {{{ */ { v8::Local r = v8js_named_property_callback(property, info, V8JS_PROP_DELETER); - if (!r.IsEmpty()) { - info.GetReturnValue().Set(r->ToBoolean()); + if (r.IsEmpty()) { + return; + } + + v8::Isolate *isolate = info.GetIsolate(); + v8::MaybeLocal value = r->ToBoolean(isolate->GetEnteredContext()); + if (!value.IsEmpty()) { + info.GetReturnValue().Set(value.ToLocalChecked()); } } /* }}} */ @@ -847,8 +881,8 @@ 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(); - v8::NamedPropertyGetterCallback getter = v8js_named_property_getter; - v8::NamedPropertyEnumeratorCallback enumerator = v8js_named_property_enumerator; + v8::GenericNamedPropertyGetterCallback getter = v8js_named_property_getter; + v8::GenericNamedPropertyEnumeratorCallback enumerator = v8js_named_property_enumerator; /* Check for ArrayAccess object */ if (V8JSG(use_array_access) && ce) { @@ -884,14 +918,14 @@ static v8::MaybeLocal v8js_wrap_object(v8::Isolate *isolate, zend_cl // Finish setup of new_tpl - inst_tpl->SetNamedPropertyHandler + inst_tpl->SetHandler(v8::NamedPropertyHandlerConfiguration (getter, /* getter */ v8js_named_property_setter, /* setter */ v8js_named_property_query, /* query */ v8js_named_property_deleter, /* deleter */ enumerator, /* enumerator */ V8JS_NULL /* data */ - ); + )); // add __invoke() handler zend_string *invoke_str = zend_string_init (ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME) - 1, 0); diff --git a/v8js_object_export.h b/v8js_object_export.h index fda29a7..3bbc840 100644 --- a/v8js_object_export.h +++ b/v8js_object_export.h @@ -25,7 +25,7 @@ typedef enum { } property_op_t; template -v8::Local v8js_named_property_callback(v8::Local property, +v8::Local v8js_named_property_callback(v8::Local property, const v8::PropertyCallbackInfo &info, property_op_t callback_type, v8::Local set_value = v8::Local()); diff --git a/v8js_v8.cc b/v8js_v8.cc index 607fb42..6abc0a4 100644 --- a/v8js_v8.cc +++ b/v8js_v8.cc @@ -108,7 +108,7 @@ void v8js_v8_init() /* {{{ */ */ void v8js_v8_call(v8js_ctx *c, zval **return_value, long flags, long time_limit, size_t memory_limit, - std::function< v8::Local(v8::Isolate *) >& v8_call) /* {{{ */ + std::function< v8::MaybeLocal(v8::Isolate *) >& v8_call) /* {{{ */ { char *tz = NULL; @@ -154,7 +154,7 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value, /* Execute script */ c->in_execution++; - v8::Local result = v8_call(c->isolate); + v8::MaybeLocal result = v8_call(c->isolate); c->in_execution--; /* Pop our context from the stack and read (possibly updated) limits @@ -238,7 +238,7 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value, /* Convert V8 value to PHP value */ if (return_value && !result.IsEmpty()) { - v8js_to_zval(result, *return_value, flags, c->isolate); + v8js_to_zval(result.ToLocalChecked(), *return_value, flags, c->isolate); } } } @@ -262,24 +262,27 @@ void v8js_terminate_execution(v8::Isolate *isolate) /* {{{ */ v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); + v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local context = v8::Local::New(isolate, ctx->context); + v8::Local source = V8JS_STR("for(;;);"); - v8::Local script = v8::Script::Compile(source); + v8::Local script = v8::Script::Compile(context, source).ToLocalChecked(); isolate->TerminateExecution(); - script->Run(); + script->Run(context); } /* }}} */ int v8js_get_properties_hash(v8::Local jsValue, HashTable *retval, int flags, v8::Isolate *isolate) /* {{{ */ { - v8::Local jsObj = jsValue->ToObject(); + v8::Local jsObj = jsValue->ToObject(isolate); if (!jsObj.IsEmpty()) { v8::Local jsKeys = jsObj->GetPropertyNames(); for (unsigned i = 0; i < jsKeys->Length(); i++) { - v8::Local jsKey = jsKeys->Get(i)->ToString(); + v8::Local jsKey = jsKeys->Get(i)->ToString(isolate); /* Skip any prototype properties */ if (!jsObj->HasOwnProperty(isolate->GetEnteredContext(), jsKey).FromMaybe(false) @@ -289,15 +292,15 @@ int v8js_get_properties_hash(v8::Local jsValue, HashTable *retval, in } v8::Local jsVal = jsObj->Get(jsKey); - v8::String::Utf8Value cstr(jsKey); + v8::String::Utf8Value cstr(isolate, jsKey); const char *c_key = ToCString(cstr); - zend_string *key = zend_string_init(c_key, jsKey->ToString()->Utf8Length(), 0); + zend_string *key = zend_string_init(c_key, jsKey->ToString(isolate)->Utf8Length(isolate), 0); zval value; ZVAL_UNDEF(&value); - if (jsVal->IsObject() && jsVal->ToObject()->InternalFieldCount() == 2) { + if (jsVal->IsObject() && jsVal->ToObject(isolate)->InternalFieldCount() == 2) { /* This is a PHP object, passed to JS and back. */ - zend_object *object = reinterpret_cast(jsVal->ToObject()->GetAlignedPointerFromInternalField(1)); + zend_object *object = reinterpret_cast(jsVal->ToObject(isolate)->GetAlignedPointerFromInternalField(1)); ZVAL_OBJ(&value, object); Z_ADDREF_P(&value); } diff --git a/v8js_v8.h b/v8js_v8.h index 16d35f8..e8ebbb6 100644 --- a/v8js_v8.h +++ b/v8js_v8.h @@ -56,7 +56,7 @@ static inline const char * ToCString(const v8::String::Utf8Value &value) /* {{{ void v8js_v8_init(); void v8js_v8_call(v8js_ctx *c, zval **return_value, long flags, long time_limit, size_t memory_limit, - std::function< v8::Local(v8::Isolate *) >& v8_call); + std::function< v8::MaybeLocal(v8::Isolate *) >& v8_call); void v8js_terminate_execution(v8::Isolate *isolate); /* Fetch V8 object properties */ diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index abc32d3..58f249b 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -73,7 +73,7 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex return retval; } - v8::Local jsObj = v8obj->ToObject(); + v8::Local jsObj = v8obj->ToObject(isolate); v8::Local jsKey = V8JS_STRL(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); v8::Local jsVal; @@ -90,7 +90,7 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex retval = !( jsVal->IsNull() || jsVal->IsUndefined() ); } else { /* empty() */ - retval = jsVal->BooleanValue(); + retval = jsVal->BooleanValue(v8_context).FromMaybe(false); /* for PHP compatibility, [] should also be empty */ if (jsVal->IsArray() && retval) { v8::Local array = v8::Local::Cast(jsVal); @@ -98,10 +98,10 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex } /* for PHP compatibility, '0' should also be empty */ if (jsVal->IsString() && retval) { - v8::Local str = jsVal->ToString(); - if (str->Length() == 1) { + v8::MaybeLocal str = jsVal->ToString(isolate); + if (!str.IsEmpty() && str.ToLocalChecked()->Length() == 1) { uint16_t c = 0; - str->Write(&c, 0, 1); + str.ToLocalChecked()->Write(isolate, &c, 0, 1); if (c == '0') { retval = false; } @@ -137,7 +137,7 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v return retval; } - v8::Local jsObj = v8obj->ToObject(); + v8::Local jsObj = v8obj->ToObject(isolate); v8::Local jsKey = V8JS_STRL(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); v8::Local jsVal; @@ -175,7 +175,7 @@ static void v8js_v8object_write_property(zval *object, zval *member, zval *value } if (v8obj->IsObject()) { - v8obj->ToObject()->CreateDataProperty(v8_context, V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))), zval_to_v8js(value, isolate)); + v8obj->ToObject(isolate)->CreateDataProperty(v8_context, V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))), zval_to_v8js(value, isolate)); } } /* }}} */ @@ -200,7 +200,7 @@ static void v8js_v8object_unset_property(zval *object, zval *member, void **cach } if (v8obj->IsObject()) { - v8obj->ToObject()->Delete(V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member)))); + v8obj->ToObject(isolate)->Delete(V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member)))); } } /* }}} */ @@ -276,7 +276,7 @@ static zend_function *v8js_v8object_get_method(zend_object **object_ptr, zend_st v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); if (!obj->v8obj.IsEmpty() && v8obj->IsObject() && !v8obj->IsFunction()) { - v8::Local jsObj = v8obj->ToObject(); + v8::Local jsObj = v8obj->ToObject(isolate); if (jsObj->Has(jsKey) && jsObj->Get(jsKey)->IsFunction()) { f = (zend_function *) ecalloc(1, sizeof(*f)); @@ -321,15 +321,16 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I /* std::function relies on its dtor to be executed, otherwise it leaks * some memory on bailout. */ { - std::function< v8::Local(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value](v8::Isolate *isolate) { + std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value](v8::Isolate *isolate) { int i = 0; + v8::Local context = v8::Local::New(isolate, obj->ctx->context); 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::Local v8obj = v8::Local::New(isolate, obj->v8obj)->ToObject(isolate); v8::Local thisObj; v8::Local cb; - if (method_name->Equals(V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME))) { + if (method_name->Equals(context, V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME)).FromMaybe(false)) { cb = v8::Local::Cast(v8obj); } else { cb = v8::Local::Cast(v8obj->Get(method_name)); @@ -545,9 +546,9 @@ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */ /* std::function relies on its dtor to be executed, otherwise it leaks * some memory on bailout. */ { - std::function< v8::Local(v8::Isolate *) > v8_call = [g](v8::Isolate *isolate) { + std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [g](v8::Isolate *isolate) { v8::Local method_name = V8JS_STR("next"); - v8::Local v8obj = v8::Local::New(isolate, g->v8obj.v8obj)->ToObject(); + v8::Local v8obj = v8::Local::New(isolate, g->v8obj.v8obj)->ToObject(isolate); v8::Local cb = v8::Local::Cast(v8obj->Get(method_name));; v8::Local result = cb->Call(v8obj, 0, NULL); @@ -563,7 +564,7 @@ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */ return V8JS_NULL; } - v8::Local resultObj = result->ToObject(); + v8::Local resultObj = result->ToObject(isolate); v8::Local val = resultObj->Get(V8JS_STR("value")); v8::Local done = resultObj->Get(V8JS_STR("done")); From 9c455081838504583e7f8851387e078c7b405a52 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Thu, 13 Sep 2018 14:01:15 +0200 Subject: [PATCH 05/13] omit use of deprecated apis --- v8js_array_access.cc | 12 ++- v8js_class.cc | 44 ++++------ v8js_convert.cc | 33 +++++--- v8js_exceptions.cc | 5 +- v8js_generator_export.cc | 10 +-- v8js_methods.cc | 87 ++++++++++++++------ v8js_object_export.cc | 114 ++++++++++++++++---------- v8js_v8.cc | 104 +++++++++++++----------- v8js_v8.h | 13 ++- v8js_v8object_class.cc | 168 ++++++++++++++++++++++----------------- 10 files changed, 351 insertions(+), 239 deletions(-) diff --git a/v8js_array_access.cc b/v8js_array_access.cc index bf7289a..e1d410e 100644 --- a/v8js_array_access.cc +++ b/v8js_array_access.cc @@ -210,11 +210,11 @@ void v8js_array_access_enumerator(const v8::PropertyCallbackInfo& inf for(int j = 0; j < length; j ++) { if(v8js_array_access_isset_p(object, j)) { - result->Set(i ++, V8JS_INT(j)); + result->Set(isolate->GetEnteredContext(), i ++, V8JS_INT(j)); } } - result->Set(V8JS_STR("length"), V8JS_INT(i)); + result->Set(isolate->GetEnteredContext(), V8JS_SYM("length"), V8JS_INT(i)); info.GetReturnValue().Set(result); } /* }}} */ @@ -244,7 +244,13 @@ void v8js_array_access_named_getter(v8::Local property_name, const v8: info.GetReturnValue().Set(ret_value); } - ret_value = prototype->ToObject(isolate)->Get(property); + v8::Local prototype_object; + if(!prototype->ToObject(isolate->GetEnteredContext()).ToLocal(&prototype_object)) { + /* ehh? Array.prototype not an object? strange, stop. */ + info.GetReturnValue().Set(ret_value); + } + + prototype_object->Get(isolate->GetEnteredContext(), property).ToLocal(&ret_value); } info.GetReturnValue().Set(ret_value); diff --git a/v8js_class.cc b/v8js_class.cc index 8430348..a415192 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -102,7 +102,7 @@ static void v8js_free_storage(zend_object *object) /* {{{ */ v8::Local v8_context = v8::Local::New(c->isolate, c->context); v8::Context::Scope context_scope(v8_context); v8::Local object_name_js = v8::Local::New(c->isolate, c->object_name); - V8JS_GLOBAL(c->isolate)->Delete(object_name_js); + V8JS_GLOBAL(c->isolate)->Delete(v8_context, object_name_js); } c->object_name.Reset(); @@ -494,8 +494,7 @@ static PHP_METHOD(V8Js, __construct) return; } - object_name_js = v8::String::NewFromUtf8(isolate, ZSTR_VAL(object_name), - v8::String::kInternalizedString, static_cast(ZSTR_LEN(object_name))); + object_name_js = V8JS_ZSYM(object_name); } else { object_name_js = V8JS_SYM("PHP"); @@ -505,7 +504,7 @@ static PHP_METHOD(V8Js, __construct) /* Add the PHP object into global object */ php_obj_t->InstanceTemplate()->SetInternalFieldCount(2); - v8::Local php_obj = php_obj_t->InstanceTemplate()->NewInstance(); + v8::Local php_obj = php_obj_t->InstanceTemplate()->NewInstance(context).ToLocalChecked(); V8JS_GLOBAL(isolate)->DefineOwnProperty(context, object_name_js, php_obj, v8::ReadOnly); /* Export public property values */ @@ -524,8 +523,7 @@ static PHP_METHOD(V8Js, __construct) return; } - v8::Local key = v8::String::NewFromUtf8(isolate, ZSTR_VAL(member), - v8::String::kInternalizedString, static_cast(ZSTR_LEN(member))); + v8::Local key = V8JS_ZSYM(member); /* Write value to PHP JS object */ value = OBJ_PROP(Z_OBJ_P(getThis()), property_info->offset); @@ -587,24 +585,16 @@ static PHP_METHOD(V8Js, __construct) return; } - v8::Local method_name = v8::String::NewFromUtf8(isolate, - ZSTR_VAL(method_ptr->common.function_name), v8::String::kInternalizedString, - static_cast(ZSTR_LEN(method_ptr->common.function_name))); + v8::Local method_name = V8JS_ZSYM(method_ptr->common.function_name); v8::Local ft; - /*try { - ft = v8::Local::New - (isolate, c->method_tmpls.at(method_ptr)); - } - catch (const std::out_of_range &) */ { - ft = v8::FunctionTemplate::New(isolate, v8js_php_callback, - v8::External::New((isolate), method_ptr)); - // @fixme add/check Signature v8::Signature::New((isolate), tmpl)); - v8js_function_tmpl_t *persistent_ft = &c->method_tmpls[method_ptr]; - persistent_ft->Reset(isolate, ft); - } + ft = v8::FunctionTemplate::New(isolate, v8js_php_callback, + v8::External::New((isolate), method_ptr)); + // @fixme add/check Signature v8::Signature::New((isolate), tmpl)); + v8js_function_tmpl_t *persistent_ft = &c->method_tmpls[method_ptr]; + persistent_ft->Reset(isolate, ft); - php_obj->CreateDataProperty(context, method_name, ft->GetFunction()); + php_obj->CreateDataProperty(context, method_name, ft->GetFunction(context).ToLocalChecked()); } ZEND_HASH_FOREACH_END(); } /* }}} */ @@ -646,7 +636,7 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze } v8::Local sname = identifier - ? v8::String::NewFromUtf8(isolate, ZSTR_VAL(identifier), v8::String::kNormalString, static_cast(ZSTR_LEN(identifier))) + ? V8JS_ZSTR(identifier) : V8JS_SYM("V8Js::compileString()"); v8::ScriptOrigin origin(sname); @@ -656,7 +646,7 @@ static void v8js_compile_script(zval *this_ptr, const zend_string *str, const ze return; } - v8::Local source = v8::String::NewFromUtf8(isolate, ZSTR_VAL(str), v8::String::kNormalString, static_cast(ZSTR_LEN(str))); + v8::Local source = V8JS_ZSTR(str); v8::MaybeLocal script = v8::Script::Compile(v8::Local::New(isolate, c->context), source, &origin); /* Compile errors? */ @@ -1164,7 +1154,7 @@ static v8::StartupData createSnapshotDataBlob(v8::SnapshotCreator *snapshot_crea v8::Context::Scope context_scope(context); v8::TryCatch try_catch(isolate); - v8::Local source = v8::String::NewFromUtf8(isolate, ZSTR_VAL(str), v8::String::kNormalString, static_cast(ZSTR_LEN(str))); + v8::Local source = V8JS_ZSTR(str); v8::MaybeLocal script = v8::Script::Compile(context, source); if (script.IsEmpty() || script.ToLocalChecked()->Run(context).IsEmpty()) @@ -1330,7 +1320,7 @@ static void v8js_write_property(zval *object, zval *member, zval *value, void ** (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(object_name_js)->ToObject(isolate); + 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, @@ -1354,7 +1344,7 @@ static void v8js_unset_property(zval *object, zval *member, void **cache_slot) / /* Global PHP JS object */ v8::Local object_name_js = v8::Local::New(isolate, c->object_name); - v8::Local jsobj = V8JS_GLOBAL(isolate)->Get(object_name_js)->ToObject(isolate); + 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, @@ -1364,7 +1354,7 @@ static void v8js_unset_property(zval *object, zval *member, void **cache_slot) / /* Delete value from PHP JS object */ v8::Local key = V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); - jsobj->Delete(key); + jsobj->Delete(v8_context, key); /* Unset from PHP object */ std_object_handlers.unset_property(object, member, NULL); diff --git a/v8js_convert.cc b/v8js_convert.cc index 3271685..332a9ed 100644 --- a/v8js_convert.cc +++ b/v8js_convert.cc @@ -79,6 +79,7 @@ static v8::Local v8js_hash_to_jsarr(zval *value, v8::Isolate *isolate return V8JS_NULL; } + v8::Local v8_context = isolate->GetEnteredContext(); newarr = v8::Array::New(isolate, i); if (i > 0) @@ -96,7 +97,7 @@ static v8::Local v8js_hash_to_jsarr(zval *value, v8::Isolate *isolate } ZEND_HASH_FOREACH_VAL(myht, data) { - newarr->Set(index++, zval_to_v8js(data, isolate)); + newarr->Set(v8_context, index++, zval_to_v8js(data, isolate)); } ZEND_HASH_FOREACH_END(); #if PHP_VERSION_ID >= 70300 @@ -114,7 +115,7 @@ static v8::Local v8js_hash_to_jsarr(zval *value, v8::Isolate *isolate v8::Local zend_long_to_v8js(zend_long v, v8::Isolate *isolate) /* {{{ */ { - if (v < - std::numeric_limits::min() || v > std::numeric_limits::max()) { + if (v < std::numeric_limits::min() || v > std::numeric_limits::max()) { return V8JS_FLOAT(static_cast(v)); } else { return V8JS_INT(static_cast(v)); @@ -148,7 +149,7 @@ v8::Local zval_to_v8js(zval *value, v8::Isolate *isolate) /* {{{ */ if (instanceof_function(Z_OBJCE_P(value), ce)) { zval dtval; zend_call_method_with_0_params(value, NULL, NULL, "getTimestamp", &dtval); - jsValue = V8JS_DATE(((double)Z_LVAL(dtval) * 1000.0)); + v8::Date::New(isolate->GetEnteredContext(), ((double)Z_LVAL(dtval) * 1000.0)).ToLocal(&jsValue); zval_dtor(&dtval); } else jsValue = v8js_hash_to_jsobj(value, isolate); @@ -164,7 +165,7 @@ v8::Local zval_to_v8js(zval *value, v8::Isolate *isolate) /* {{{ */ break; } - jsValue = v8::String::NewFromUtf8(isolate, ZSTR_VAL(value_str), v8::String::kNormalString, static_cast(ZSTR_LEN(value_str))); + jsValue = V8JS_ZSTR(value_str); break; case IS_LONG: @@ -201,33 +202,37 @@ v8::Local zval_to_v8js(zval *value, v8::Isolate *isolate) /* {{{ */ int v8js_to_zval(v8::Local jsValue, zval *return_value, int flags, v8::Isolate *isolate) /* {{{ */ { v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local v8_context = v8::Local::New(isolate, ctx->context); if (jsValue->IsString()) { v8::String::Utf8Value str(isolate, jsValue); const char *cstr = ToCString(str); - RETVAL_STRINGL(cstr, jsValue->ToString(isolate)->Utf8Length(isolate)); + RETVAL_STRINGL(cstr, str.length()); } else if (jsValue->IsBoolean()) { - v8::Maybe value = jsValue->BooleanValue(v8::Local::New(isolate, ctx->context)); - if (value.IsNothing()) { + v8::Maybe value = jsValue->BooleanValue(v8_context); + if (value.IsNothing()) + { return FAILURE; } RETVAL_BOOL(value.ToChecked()); } else if (jsValue->IsInt32() || jsValue->IsUint32()) { - v8::Maybe value = jsValue->IntegerValue(v8::Local::New(isolate, ctx->context)); - if (value.IsNothing()) { + v8::Maybe value = jsValue->IntegerValue(v8_context); + if (value.IsNothing()) + { return FAILURE; } RETVAL_LONG((long) value.ToChecked()); } else if (jsValue->IsNumber()) { - v8::Maybe value = jsValue->NumberValue(v8::Local::New(isolate, ctx->context)); - if (value.IsNothing()) { + v8::Maybe value = jsValue->NumberValue(v8_context); + if (value.IsNothing()) + { return FAILURE; } RETVAL_DOUBLE(value.ToChecked()); @@ -267,7 +272,11 @@ int v8js_to_zval(v8::Local jsValue, zval *return_value, int flags, v8 } else if (jsValue->IsObject()) { - v8::Local self = jsValue->ToObject(isolate); + v8::Local self; + if (!jsValue->ToObject(v8_context).ToLocal(&self)) + { + return FAILURE; + } // if this is a wrapped PHP object, then just unwrap it. if (self->InternalFieldCount() == 2) { diff --git a/v8js_exceptions.cc b/v8js_exceptions.cc index 2947198..4ec809b 100644 --- a/v8js_exceptions.cc +++ b/v8js_exceptions.cc @@ -92,8 +92,9 @@ void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8:: PHPV8_EXPROP(_string, JsTrace, ToCString(stacktrace)); } - if(try_catch->Exception()->IsObject() && try_catch->Exception()->ToObject(isolate)->InternalFieldCount() == 2) { - zend_object *php_exception = reinterpret_cast(try_catch->Exception()->ToObject(isolate)->GetAlignedPointerFromInternalField(1)); + v8::Local error_object; + if(try_catch->Exception()->IsObject() && try_catch->Exception()->ToObject(context).ToLocal(&error_object) && error_object->InternalFieldCount() == 2) { + zend_object *php_exception = reinterpret_cast(error_object->GetAlignedPointerFromInternalField(1)); zend_class_entry *exception_ce = zend_exception_get_default(); if (instanceof_function(php_exception->ce, exception_ce)) { diff --git a/v8js_generator_export.cc b/v8js_generator_export.cc index 2d5f1ce..84d7317 100644 --- a/v8js_generator_export.cc +++ b/v8js_generator_export.cc @@ -25,10 +25,10 @@ v8::Local v8js_wrap_generator(v8::Isolate *isolate, v8::LocalIsObject()); v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); - v8::Local context = v8::Local::New(isolate, ctx->context); + v8::Local v8_context = v8::Local::New(isolate, ctx->context); v8::TryCatch try_catch(isolate); - v8::Local source = v8::String::NewFromUtf8(isolate, "(\ + v8::Local source = V8JS_SYM("(\ function(wrapped_object) { \ return (function*() { \ for(;;) { \ @@ -40,14 +40,14 @@ function(wrapped_object) { \ } \ })(); \ })"); - v8::MaybeLocal script = v8::Script::Compile(context, source); + v8::MaybeLocal script = v8::Script::Compile(v8_context, source); if(script.IsEmpty()) { zend_error(E_ERROR, "Failed to compile Generator object wrapper"); return result; } - v8::MaybeLocal wrapper_fn_val = script.ToLocalChecked()->Run(context); + v8::MaybeLocal wrapper_fn_val = script.ToLocalChecked()->Run(v8_context); if(wrapper_fn_val.IsEmpty() || !wrapper_fn_val.ToLocalChecked()->IsFunction()) { zend_error(E_ERROR, "Failed to create Generator object wrapper function"); @@ -60,7 +60,7 @@ function(wrapped_object) { \ new(&jsArgv[0]) v8::Local; jsArgv[0] = v8::Local::New(isolate, wrapped_object); - result = wrapper_fn->Call(V8JS_GLOBAL(isolate), 1, jsArgv); + wrapper_fn->Call(v8_context, V8JS_GLOBAL(isolate), 1, jsArgv).ToLocal(&result); return result; } /* }}} */ diff --git a/v8js_methods.cc b/v8js_methods.cc index cd761bd..9ef9967 100644 --- a/v8js_methods.cc +++ b/v8js_methods.cc @@ -65,7 +65,7 @@ V8JS_METHOD(print) /* {{{ */ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int level) /* {{{ */ { v8js_ctx *c = (v8js_ctx *) isolate->GetData(0); - v8::Local context = v8::Local::New(isolate, c->context); + v8::Local v8_context = v8::Local::New(isolate, c->context); if (level > 1) { php_printf("%*c", (level - 1) * 2, ' '); @@ -83,7 +83,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve } if (var->IsInt32()) { - v8::Maybe value = var->IntegerValue(context); + v8::Maybe value = var->IntegerValue(v8_context); if (value.IsNothing()) { php_printf("\n"); @@ -96,7 +96,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve } if (var->IsUint32()) { - v8::Maybe value = var->Uint32Value(context); + v8::Maybe value = var->Uint32Value(v8_context); if (value.IsNothing()) { php_printf("\n"); @@ -109,7 +109,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve } if (var->IsNumber()) { - v8::Maybe value = var->NumberValue(context); + v8::Maybe value = var->NumberValue(v8_context); if (value.IsNothing()) { php_printf("\n"); @@ -122,7 +122,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve } if (var->IsBoolean()) { - v8::Maybe value = var->BooleanValue(context); + v8::Maybe value = var->BooleanValue(v8_context); if (value.IsNothing()) { php_printf("\n"); @@ -142,7 +142,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve details = re->GetSource(); } else { - details = var->ToDetailString(context).FromMaybe(v8::Local()); + details = var->ToDetailString(v8_context).FromMaybe(v8::Local()); if (try_catch.HasCaught()) { details = V8JS_SYM(""); @@ -151,7 +151,7 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve v8::String::Utf8Value str(isolate, details); const char *valstr = ToCString(str); - size_t valstr_len = details->ToString(isolate)->Utf8Length(isolate); + size_t valstr_len = str.length(); if (var->IsString()) { @@ -177,7 +177,16 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve for (unsigned i = 0; i < length; i++) { php_printf("%*c[%d] =>\n", level * 2, ' ', i); - v8js_dumper(isolate, array->Get(i), level + 1); + + v8::MaybeLocal value = array->Get(v8_context, i); + if (value.IsEmpty()) + { + php_printf("\n"); + } + else + { + v8js_dumper(isolate, value.ToLocalChecked(), level + 1); + } } if (level > 1) { @@ -194,13 +203,23 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve if (var->IsFunction() && strcmp(ToCString(cname), "Closure") != 0) { - v8::String::Utf8Value csource(isolate, object->ToString(isolate)); - php_printf("object(Closure)#%d {\n%*c%s\n", hash, level * 2 + 2, ' ', ToCString(csource)); + php_printf("object(Closure)#%d {\n%*c", hash, level * 2 + 2, ' '); + + v8::Local source; + if (object->ToString(v8_context).ToLocal(&source)) + { + v8::String::Utf8Value csource(isolate, source); + php_printf("%s\n", ToCString(csource)); + } + else + { + php_printf("\n"); + } } else { - v8::Local keys = object->GetOwnPropertyNames(); - uint32_t length = keys->Length(); + v8::MaybeLocal keys = object->GetOwnPropertyNames(v8_context); + uint32_t length = keys.IsEmpty() ? 0 : keys.ToLocalChecked()->Length(); if (strcmp(ToCString(cname), "Array") == 0 || strcmp(ToCString(cname), "V8Object") == 0) { @@ -211,10 +230,26 @@ static void v8js_dumper(v8::Isolate *isolate, v8::Local var, int leve php_printf(" (%d) {\n", length); for (unsigned i = 0; i < length; i++) { - v8::Local key = keys->Get(i)->ToString(isolate); - v8::String::Utf8Value kname(isolate, key); - php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(kname)); - v8js_dumper(isolate, object->Get(key), level + 1); + v8::MaybeLocal key_slot = keys.ToLocalChecked()->Get(v8_context, i); + v8::Local key; + + if (key_slot.IsEmpty() || !key_slot.ToLocalChecked()->ToString(v8_context).ToLocal(&key)) + { + key = V8JS_SYM(""); + } + + v8::String::Utf8Value key_name(isolate, key); + php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(key_name)); + + v8::MaybeLocal value = object->Get(v8_context, key); + if (value.IsEmpty()) + { + php_printf("\n"); + } + else + { + v8js_dumper(isolate, value.ToLocalChecked(), level + 1); + } } } @@ -385,7 +420,9 @@ V8JS_METHOD(require) if (c->modules_loaded.count(normalised_module_id) > 0) { v8::Persistent newobj; newobj.Reset(isolate, c->modules_loaded[normalised_module_id]); - info.GetReturnValue().Set(newobj); + + // TODO store v8::Global in c->modules_loaded directly!? + info.GetReturnValue().Set(v8::Global(isolate, newobj)); efree(normalised_module_id); efree(normalised_path); @@ -449,7 +486,7 @@ V8JS_METHOD(require) } if(Z_TYPE(module_code) == IS_OBJECT) { - v8::Local newobj = zval_to_v8js(&module_code, isolate)->ToObject(isolate); + v8::Local newobj = zval_to_v8js(&module_code, isolate)->ToObject(isolate->GetEnteredContext()).ToLocalChecked(); c->modules_loaded[normalised_module_id].Reset(isolate, newobj); info.GetReturnValue().Set(newobj); @@ -503,7 +540,7 @@ V8JS_METHOD(require) } v8::Local base_path = V8JS_STR(normalised_path); - v8::MaybeLocal require_fn = v8::FunctionTemplate::New(isolate, V8JS_MN(require), base_path)->GetFunction(); + v8::MaybeLocal require_fn = v8::FunctionTemplate::New(isolate, V8JS_MN(require), base_path)->GetFunction(context); if (require_fn.IsEmpty()) { efree(normalised_path); @@ -523,8 +560,8 @@ V8JS_METHOD(require) v8::Local exports = v8::Object::New(isolate); v8::Local module = v8::Object::New(isolate); - module->Set(V8JS_SYM("id"), V8JS_STR(normalised_module_id)); - module->Set(V8JS_SYM("exports"), exports); + module->Set(context, V8JS_SYM("id"), V8JS_STR(normalised_module_id)); + module->Set(context, V8JS_SYM("exports"), exports); if (!module_function.IsEmpty() && module_function.ToLocalChecked()->IsFunction()) { v8::Local *jsArgv = static_cast *>(alloca(3 * sizeof(v8::Local))); @@ -538,7 +575,7 @@ V8JS_METHOD(require) jsArgv[2] = require_fn.ToLocalChecked(); // actually call the module - v8::Local::Cast(module_function.ToLocalChecked())->Call(exports, 3, jsArgv); + v8::Local::Cast(module_function.ToLocalChecked())->Call(context, exports, 3, jsArgv); } // Remove this module and path from the stack @@ -571,8 +608,10 @@ V8JS_METHOD(require) // Cache the module so it doesn't need to be compiled and run again // Ensure compatibility with CommonJS implementations such as NodeJS by playing nicely with module.exports and exports - if (module->Has(V8JS_SYM("exports"))) { - newobj = module->Get(V8JS_SYM("exports")); + v8::Local sym_exports = V8JS_SYM("exports"); + if (module->Has(context, sym_exports).FromMaybe(false)) + { + module->Get(context, sym_exports).ToLocal(&newobj); } c->modules_loaded[normalised_module_id].Reset(isolate, newobj); diff --git a/v8js_object_export.cc b/v8js_object_export.cc index 6a01009..b36574c 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -35,8 +35,10 @@ extern "C" { static void v8js_weak_object_callback(const v8::WeakCallbackInfo &data); /* Callback for PHP methods and functions */ -static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v8::Isolate *isolate, const v8::FunctionCallbackInfo& info) /* {{{ */ +static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, const v8::FunctionCallbackInfo& info) /* {{{ */ { + v8::Isolate *isolate = info.GetIsolate(); + v8::Local v8_context = isolate->GetEnteredContext(); v8::Local return_value = V8JS_NULL; zend_fcall_info fci; zend_fcall_info_cache fcc; @@ -97,16 +99,24 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v } /* Convert parameters passed from V8 */ - if (argc) { + if (argc) + { fci.params = (zval *) safe_emalloc(argc, sizeof(zval), 0); - for (i = 0; i < argc; i++) { - if (info[i]->IsObject() && info[i]->ToObject(isolate)->InternalFieldCount() == 2) { + for (i = 0; i < argc; i++) + { + v8::Local param_object; + + if (info[i]->IsObject() && info[i]->ToObject(v8_context).ToLocal(¶m_object) && param_object->InternalFieldCount() == 2) + { /* This is a PHP object, passed to JS and back. */ - zend_object *object = reinterpret_cast(info[i]->ToObject(isolate)->GetAlignedPointerFromInternalField(1)); + zend_object *object = reinterpret_cast(param_object->GetAlignedPointerFromInternalField(1)); ZVAL_OBJ(&fci.params[i], object); Z_ADDREF_P(&fci.params[i]); - } else { - if (v8js_to_zval(info[i], &fci.params[i], ctx->flags, isolate) == FAILURE) { + } + else + { + if (v8js_to_zval(info[i], &fci.params[i], ctx->flags, isolate) == FAILURE) + { error_len = spprintf(&error, 0, "converting parameter #%d passed to %s() failed", i + 1, method_ptr->common.function_name); if (error_len > std::numeric_limits::max()) { @@ -190,7 +200,6 @@ failure: /* Callback for PHP methods and functions */ void v8js_php_callback(const v8::FunctionCallbackInfo& info) /* {{{ */ { - v8::Isolate *isolate = info.GetIsolate(); v8::Local self = info.Holder(); zend_object *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); @@ -203,7 +212,7 @@ void v8js_php_callback(const v8::FunctionCallbackInfo& info) /* {{{ * method_ptr = zend_get_closure_invoke_method(object); } - return v8js_call_php_func(object, method_ptr, isolate, info); + return v8js_call_php_func(object, method_ptr, info); } /* Callback for PHP constructor calls */ @@ -220,8 +229,16 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i } v8::Local cons_data = v8::Local::Cast(info.Data()); - v8::Local ext_tmpl = v8::Local::Cast(cons_data->Get(0)); - v8::Local ext_ce = v8::Local::Cast(cons_data->Get(1)); + v8::Local cons_tmpl, cons_ce; + + if (!cons_data->Get(isolate->GetEnteredContext(), 0).ToLocal(&cons_tmpl) + ||!cons_data->Get(isolate->GetEnteredContext(), 1).ToLocal(&cons_ce)) + { + return; + } + + v8::Local ext_tmpl = v8::Local::Cast(cons_tmpl); + v8::Local ext_ce = v8::Local::Cast(cons_ce); v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); @@ -257,7 +274,7 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i // Call __construct function if (ctor_ptr != NULL) { - v8js_call_php_func(Z_OBJ(value), ctor_ptr, isolate, info); + v8js_call_php_func(Z_OBJ(value), ctor_ptr, info); } } @@ -311,13 +328,15 @@ static void v8js_weak_closure_callback(const v8::WeakCallbackInfoGetFunction() + (v8::FunctionTemplate::New((isolate), v8js_php_callback, v8::External::New((isolate), mptr), v8::Signature::New((isolate), tmpl))->GetFunction(isolate->GetEnteredContext()).ToLocalChecked()) static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo &info) /* {{{ */ { // note: 'special' properties like 'constructor' are not enumerated. v8::Isolate *isolate = info.GetIsolate(); + v8::Local v8_context = isolate->GetEnteredContext(); + v8::Local self = info.Holder(); v8::Local result = v8::Array::New(isolate, 0); uint32_t result_len = 0; @@ -372,7 +391,7 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfocommon.function_name), static_cast(ZSTR_LEN(method_ptr->common.function_name))); } - result->Set(result_len++, method_name); + result->Set(v8_context, result_len++, method_name); } ZEND_HASH_FOREACH_END(); /* enumerate all properties */ @@ -400,11 +419,11 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo(emalloc(ZSTR_LEN(key) + 2)); prefixed[0] = '$'; strncpy(prefixed + 1, ZSTR_VAL(key), ZSTR_LEN(key) + 1); - result->Set(result_len++, V8JS_STRL(prefixed, static_cast(ZSTR_LEN(key) + 1))); + result->Set(v8_context, result_len++, V8JS_STRL(prefixed, static_cast(ZSTR_LEN(key) + 1))); efree(prefixed); } else { // even numeric indices are enumerated as strings in JavaScript - result->Set(result_len++, V8JS_FLOAT((double) index)->ToString(isolate)); + result->Set(v8_context, result_len++, V8JS_FLOAT((double) index)->ToString(v8_context).ToLocalChecked()); } } ZEND_HASH_FOREACH_END(); @@ -416,6 +435,8 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo& info) /* {{{ */ { v8::Isolate *isolate = info.GetIsolate(); + v8::Local v8_context = isolate->GetEnteredContext(); + v8::Local self = info.Holder(); v8::Local cb = v8::Local::Cast(info.Data()); int argc = info.Length(), i; @@ -430,9 +451,9 @@ static void v8js_invoke_callback(const v8::FunctionCallbackInfo& info if (info.IsConstructCall()) { v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); - v8::MaybeLocal str = self->GetConstructorName()->ToString(isolate); - v8::String::Utf8Value str_value(isolate, str.ToLocalChecked()); - zend_string *constructor_name = zend_string_init(ToCString(str_value), str.ToLocalChecked()->Utf8Length(isolate), 0); + v8::Local str = self->GetConstructorName()->ToString(v8_context).ToLocalChecked(); + v8::String::Utf8Value str_value(isolate, str); + zend_string *constructor_name = zend_string_init(ToCString(str_value), str_value.length(), 0); zend_class_entry *ce = zend_lookup_class(constructor_name); zend_string_release(constructor_name); @@ -440,15 +461,13 @@ static void v8js_invoke_callback(const v8::FunctionCallbackInfo& info new_tpl = v8::Local::New (isolate, ctx->template_cache.at(ce->name)); - v8::MaybeLocal maybeResult = new_tpl->GetFunction()->NewInstance(isolate->GetEnteredContext(), argc, argv); - - if (!maybeResult.IsEmpty()) { - result = maybeResult.ToLocalChecked(); - } else { + v8::Local fn; + if (!new_tpl->GetFunction(v8_context).ToLocal(&fn) || !fn->NewInstance(v8_context, argc, argv).ToLocal(&result)) + { result = V8JS_UNDEFINED; } } else { - result = cb->Call(self, argc, argv); + cb->Call(v8_context, self, argc, argv).ToLocal(&result); } info.GetReturnValue().Set(result); @@ -461,6 +480,8 @@ static void v8js_invoke_callback(const v8::FunctionCallbackInfo& info static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) /* {{{ */ { v8::Isolate *isolate = info.GetIsolate(); + v8::Local v8_context = isolate->GetEnteredContext(); + v8::Local self = info.Holder(); v8::Local return_value = V8JS_NULL; @@ -529,7 +550,7 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) return; } - v8::MaybeLocal str = info[0]->ToString(isolate); + v8::MaybeLocal str = info[0]->ToString(v8_context); if (str.IsEmpty()) { @@ -552,7 +573,7 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) v8::String::Utf8Value str_value(isolate, str.ToLocalChecked()); const char *method_c_name = ToCString(str_value); - zend_string *method_name = zend_string_init(method_c_name, str.ToLocalChecked()->Utf8Length(isolate), 0); + zend_string *method_name = zend_string_init(method_c_name, str_value.length(), 0); // okay, look up the method name and manually invoke it. const zend_object_handlers *h = object->handlers; @@ -588,9 +609,9 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) v8::Local *argv = static_cast *>(alloca(sizeof(v8::Local) * argc)); for (i=0; i; - argv[i] = args->Get(i); + args->Get(v8_context, i).ToLocal(&argv[i]); } - return_value = cb->Call(info.This(), (int) argc, argv); + cb->Call(v8_context, info.This(), (int) argc, argv).ToLocal(&return_value); info.GetReturnValue().Set(return_value); } /* }}} */ @@ -602,10 +623,11 @@ v8::Local v8js_named_property_callback(v8::Local property_n v8::Local property = v8::Local::Cast(property_name); v8::Isolate *isolate = info.GetIsolate(); + v8::Local v8_context = isolate->GetEnteredContext(); v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); v8::String::Utf8Value cstr(isolate, property); const char *name = ToCString(cstr); - uint name_len = property->Utf8Length(isolate); + uint name_len = cstr.length(); char *lower = estrndup(name, name_len); zend_string *method_name; @@ -668,9 +690,13 @@ v8::Local v8js_named_property_callback(v8::Local property_n v8js_function_tmpl_t *persistent_ft = &ctx->call_impls[tmpl_ptr]; persistent_ft->Reset(isolate, ft); } - v8::Local cb = ft->GetFunction(); - cb->SetName(property); - ret_value = cb; + + v8::Local fn; + if (ft->GetFunction(v8_context).ToLocal(&fn)) + { + fn->SetName(property); + ret_value = fn; + } } else { v8::Local ft; try { @@ -684,7 +710,7 @@ v8::Local v8js_named_property_callback(v8::Local property_n v8js_function_tmpl_t *persistent_ft = &ctx->method_tmpls[method_ptr]; persistent_ft->Reset(isolate, ft); } - ret_value = ft->GetFunction(); + ft->GetFunction(v8_context).ToLocal(&ret_value); } } } else if (callback_type == V8JS_PROP_QUERY) { @@ -849,6 +875,7 @@ static void v8js_named_property_deleter(v8::Local property, const v8:: static v8::MaybeLocal v8js_wrap_object(v8::Isolate *isolate, zend_class_entry *ce, zval *value) /* {{{ */ { v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local v8_context = v8::Local::New(isolate, ctx->context); v8::Local new_tpl; v8js_function_tmpl_t *persist_tpl_; @@ -938,14 +965,20 @@ static v8::MaybeLocal v8js_wrap_object(v8::Isolate *isolate, zend_cl zend_string_release(invoke_str); } v8::Local call_handler_data = v8::Array::New(isolate, 2); - call_handler_data->Set(0, v8::External::New(isolate, persist_tpl_)); - call_handler_data->Set(1, v8::External::New(isolate, ce)); + call_handler_data->Set(v8_context, 0, v8::External::New(isolate, persist_tpl_)); + call_handler_data->Set(v8_context, 1, v8::External::New(isolate, ce)); new_tpl->SetCallHandler(v8js_construct_callback, call_handler_data); } // Create v8 wrapper object v8::Local external = v8::External::New(isolate, Z_OBJ_P(value)); - v8::MaybeLocal newobj = new_tpl->GetFunction()->NewInstance(isolate->GetEnteredContext(), 1, &external); + + v8::Local constr; + if (!new_tpl->GetFunction(v8_context).ToLocal(&constr)) { + return v8::MaybeLocal(); + } + + v8::MaybeLocal newobj = constr->NewInstance(v8_context, 1, &external); if (ce == zend_ce_closure && !newobj.IsEmpty()) { // free uncached function template when object is freed @@ -965,6 +998,7 @@ static v8::Local v8js_wrap_array_to_object(v8::Isolate *isolate, zva zend_ulong index; v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local v8_context = v8::Local::New(isolate, ctx->context); v8::Local new_tpl; if(ctx->array_tmpl.IsEmpty()) { @@ -981,7 +1015,7 @@ static v8::Local v8js_wrap_array_to_object(v8::Isolate *isolate, zva new_tpl = v8::Local::New(isolate, ctx->array_tmpl); } - v8::Local newobj = new_tpl->InstanceTemplate()->NewInstance(); + v8::Local newobj = new_tpl->InstanceTemplate()->NewInstance(v8_context).ToLocalChecked(); HashTable *myht = HASH_OF(value); i = myht ? zend_hash_num_elements(myht) : 0; @@ -1012,7 +1046,7 @@ static v8::Local v8js_wrap_array_to_object(v8::Isolate *isolate, zva continue; } - newobj->Set(V8JS_STRL(ZSTR_VAL(key), static_cast(ZSTR_LEN(key))), + newobj->Set(v8_context, V8JS_STRL(ZSTR_VAL(key), static_cast(ZSTR_LEN(key))), zval_to_v8js(data, isolate)); } else { if (index > std::numeric_limits::max()) { @@ -1021,7 +1055,7 @@ static v8::Local v8js_wrap_array_to_object(v8::Isolate *isolate, zva continue; } - newobj->Set(static_cast(index), zval_to_v8js(data, isolate)); + newobj->Set(v8_context, static_cast(index), zval_to_v8js(data, isolate)); } } ZEND_HASH_FOREACH_END(); diff --git a/v8js_v8.cc b/v8js_v8.cc index 6abc0a4..5c7393d 100644 --- a/v8js_v8.cc +++ b/v8js_v8.cc @@ -275,53 +275,67 @@ void v8js_terminate_execution(v8::Isolate *isolate) /* {{{ */ int v8js_get_properties_hash(v8::Local jsValue, HashTable *retval, int flags, v8::Isolate *isolate) /* {{{ */ { - v8::Local jsObj = jsValue->ToObject(isolate); + v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); + v8::Local v8_context = v8::Local::New(isolate, ctx->context); - if (!jsObj.IsEmpty()) { - v8::Local jsKeys = jsObj->GetPropertyNames(); - - for (unsigned i = 0; i < jsKeys->Length(); i++) - { - v8::Local jsKey = jsKeys->Get(i)->ToString(isolate); - - /* Skip any prototype properties */ - if (!jsObj->HasOwnProperty(isolate->GetEnteredContext(), jsKey).FromMaybe(false) - && !jsObj->HasRealNamedProperty(jsKey) - && !jsObj->HasRealNamedCallbackProperty(jsKey)) { - continue; - } - - v8::Local jsVal = jsObj->Get(jsKey); - v8::String::Utf8Value cstr(isolate, jsKey); - const char *c_key = ToCString(cstr); - zend_string *key = zend_string_init(c_key, jsKey->ToString(isolate)->Utf8Length(isolate), 0); - zval value; - ZVAL_UNDEF(&value); - - if (jsVal->IsObject() && jsVal->ToObject(isolate)->InternalFieldCount() == 2) { - /* This is a PHP object, passed to JS and back. */ - zend_object *object = reinterpret_cast(jsVal->ToObject(isolate)->GetAlignedPointerFromInternalField(1)); - ZVAL_OBJ(&value, object); - Z_ADDREF_P(&value); - } - else { - if (v8js_to_zval(jsVal, &value, flags, isolate) == FAILURE) { - zval_ptr_dtor(&value); - return FAILURE; - } - } - - if ((flags & V8JS_FLAG_FORCE_ARRAY) || jsValue->IsArray()) { - zend_symtable_update(retval, key, &value); - } else { - zend_hash_update(retval, key, &value); - } - - zend_string_release(key); - } - return SUCCESS; + v8::Local jsObj; + v8::Local jsKeys; + if (!jsValue->ToObject(v8_context).ToLocal(&jsObj) + || !jsObj->GetPropertyNames(v8_context).ToLocal(&jsKeys)) { + return FAILURE; } - return FAILURE; + + for (unsigned i = 0; i < jsKeys->Length(); i++) + { + v8::Local jsKeySlot; + v8::Local jsKey; + + if (!jsKeys->Get(v8_context, i).ToLocal(&jsKeySlot) + || !jsKeySlot->ToString(v8_context).ToLocal(&jsKey)) { + continue; + } + + /* Skip any prototype properties */ + if (!jsObj->HasOwnProperty(isolate->GetEnteredContext(), jsKey).FromMaybe(false) + && !jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) + && !jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) { + continue; + } + + v8::Local jsVal; + + if (!jsObj->Get(v8_context, jsKey).ToLocal(&jsVal)) { + continue; + } + + v8::String::Utf8Value cstr(isolate, jsKey); + zend_string *key = zend_string_init(ToCString(cstr), cstr.length(), 0); + zval value; + ZVAL_UNDEF(&value); + + v8::Local jsValObject; + if (jsVal->IsObject() && jsVal->ToObject(v8_context).ToLocal(&jsValObject) && jsValObject->InternalFieldCount() == 2) { + /* This is a PHP object, passed to JS and back. */ + zend_object *object = reinterpret_cast(jsValObject->GetAlignedPointerFromInternalField(1)); + ZVAL_OBJ(&value, object); + Z_ADDREF_P(&value); + } + else { + if (v8js_to_zval(jsVal, &value, flags, isolate) == FAILURE) { + zval_ptr_dtor(&value); + return FAILURE; + } + } + + if ((flags & V8JS_FLAG_FORCE_ARRAY) || jsValue->IsArray()) { + zend_symtable_update(retval, key, &value); + } else { + zend_hash_update(retval, key, &value); + } + + zend_string_release(key); + } + return SUCCESS; } /* }}} */ diff --git a/v8js_v8.h b/v8js_v8.h index e8ebbb6..22729f1 100644 --- a/v8js_v8.h +++ b/v8js_v8.h @@ -17,19 +17,18 @@ #include /* Helper macros */ -#define V8JS_SYM(v) v8::String::NewFromUtf8(isolate, v, v8::String::kInternalizedString, sizeof(v) - 1) -#define V8JS_SYML(v, l) v8::String::NewFromUtf8(isolate, v, v8::String::kInternalizedString, l) -#define V8JS_ZSYM(v) v8::String::NewFromUtf8(isolate, ZSTR_VAL(v), v8::String::kInternalizedString, ZSTR_LEN(v)) -#define V8JS_STR(v) v8::String::NewFromUtf8(isolate, v) -#define V8JS_STRL(v, l) v8::String::NewFromUtf8(isolate, v, v8::String::kNormalString, l) -#define V8JS_ZSTR(v) v8::String::NewFromUtf8(isolate, ZSTR_VAL(v), v8::String::kNormalString, ZSTR_LEN(v)) +#define V8JS_SYM(v) (v8::String::NewFromUtf8(isolate, v, v8::NewStringType::kInternalized, sizeof(v) - 1).ToLocalChecked()) +#define V8JS_SYML(v, l) (v8::String::NewFromUtf8(isolate, v, v8::NewStringType::kInternalized, l).ToLocalChecked()) +#define V8JS_ZSYM(v) (v8::String::NewFromUtf8(isolate, ZSTR_VAL(v), v8::NewStringType::kInternalized, ZSTR_LEN(v)).ToLocalChecked()) +#define V8JS_STR(v) (v8::String::NewFromUtf8(isolate, v, v8::NewStringType::kNormal).ToLocalChecked()) +#define V8JS_STRL(v, l) (v8::String::NewFromUtf8(isolate, v, v8::NewStringType::kNormal, l).ToLocalChecked()) +#define V8JS_ZSTR(v) (v8::String::NewFromUtf8(isolate, ZSTR_VAL(v), v8::NewStringType::kNormal, ZSTR_LEN(v)).ToLocalChecked()) #define V8JS_INT(v) v8::Integer::New(isolate, v) #define V8JS_UINT(v) v8::Integer::NewFromUnsigned(isolate, v) #define V8JS_FLOAT(v) v8::Number::New(isolate, v) #define V8JS_BOOL(v) ((v)?v8::True(isolate):v8::False(isolate)) #define V8JS_TRUE() v8::True(isolate) #define V8JS_FALSE() v8::False(isolate) -#define V8JS_DATE(v) v8::Date::New(isolate, v) #define V8JS_NULL v8::Null(isolate) #define V8JS_UNDEFINED v8::Undefined(isolate) #define V8JS_MN(name) v8js_method_##name diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index 58f249b..9440e19 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -59,58 +59,64 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex if (!obj->ctx) { zend_throw_exception(php_ce_v8js_exception, "Can't access V8Object after V8Js instance is destroyed!", 0); - return retval; + return false; } - V8JS_CTX_PROLOGUE_EX(obj->ctx, retval); + V8JS_CTX_PROLOGUE_EX(obj->ctx, false); v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); + v8::Local jsObj; - if (Z_TYPE_P(member) == IS_STRING && v8obj->IsObject()) - { - 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 retval; - } + if (Z_TYPE_P(member) != IS_STRING || !v8obj->IsObject() || !v8obj->ToObject(v8_context).ToLocal(&jsObj)) { + return false; + } - v8::Local jsObj = v8obj->ToObject(isolate); - v8::Local jsKey = V8JS_STRL(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); - v8::Local jsVal; + 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 false; + } - /* Skip any prototype properties */ - if (jsObj->HasRealNamedProperty(jsKey) || jsObj->HasRealNamedCallbackProperty(jsKey)) { - if (has_set_exists == 2) { - /* property_exists(), that's enough! */ - retval = true; - } else { - /* We need to look at the value. */ - jsVal = jsObj->Get(jsKey); - if (has_set_exists == 0 ) { - /* isset(): We make 'undefined' equivalent to 'null' */ - retval = !( jsVal->IsNull() || jsVal->IsUndefined() ); - } else { - /* empty() */ - retval = jsVal->BooleanValue(v8_context).FromMaybe(false); - /* for PHP compatibility, [] should also be empty */ - if (jsVal->IsArray() && retval) { - v8::Local array = v8::Local::Cast(jsVal); - retval = (array->Length() != 0); - } - /* for PHP compatibility, '0' should also be empty */ - if (jsVal->IsString() && retval) { - v8::MaybeLocal str = jsVal->ToString(isolate); - if (!str.IsEmpty() && str.ToLocalChecked()->Length() == 1) { - uint16_t c = 0; - str.ToLocalChecked()->Write(isolate, &c, 0, 1); - if (c == '0') { - retval = false; - } - } - } - } - } + v8::Local jsKey = V8JS_ZSYM(Z_STR_P(member)); + + /* Skip any prototype properties */ + if (!jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) + && !jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) { + return false; + } + + if (has_set_exists == 2) { + /* property_exists(), that's enough! */ + return true; + } + + /* We need to look at the value. */ + v8::Local jsVal = jsObj->Get(v8_context, jsKey).ToLocalChecked(); + + if (has_set_exists == 0 ) { + /* isset(): We make 'undefined' equivalent to 'null' */ + return !( jsVal->IsNull() || jsVal->IsUndefined() ); + } + + /* empty() */ + retval = jsVal->BooleanValue(v8_context).FromMaybe(false); + + /* for PHP compatibility, [] should also be empty */ + 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) { + uint16_t c = 0; + str->Write(isolate, &c, 0, 1); + if (c == '0') { + retval = false; } } + return retval; } /* }}} */ @@ -137,15 +143,15 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v return retval; } - v8::Local jsObj = v8obj->ToObject(isolate); - v8::Local jsKey = V8JS_STRL(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))); - v8::Local jsVal; + v8::Local jsKey = V8JS_ZSYM(Z_STR_P(member)); + v8::Local jsObj = v8obj->ToObject(v8_context).ToLocalChecked(); /* Skip any prototype properties */ - if (jsObj->HasRealNamedProperty(jsKey) || jsObj->HasRealNamedCallbackProperty(jsKey)) { - jsVal = jsObj->Get(jsKey); + if (jsObj->HasRealNamedProperty(v8_context, jsKey).FromMaybe(false) + || jsObj->HasRealNamedCallbackProperty(v8_context, jsKey).FromMaybe(false)) { + v8::MaybeLocal jsVal = jsObj->Get(v8_context, jsKey); - if (v8js_to_zval(jsVal, retval, obj->flags, isolate) == SUCCESS) { + if (!jsVal.IsEmpty() && v8js_to_zval(jsVal.ToLocalChecked(), retval, obj->flags, isolate) == SUCCESS) { return retval; } } @@ -166,7 +172,7 @@ static void v8js_v8object_write_property(zval *object, zval *member, zval *value } V8JS_CTX_PROLOGUE(obj->ctx); - v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); + 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, @@ -174,8 +180,9 @@ static void v8js_v8object_write_property(zval *object, zval *member, zval *value return; } - if (v8obj->IsObject()) { - v8obj->ToObject(isolate)->CreateDataProperty(v8_context, V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member))), zval_to_v8js(value, isolate)); + 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)); } } /* }}} */ @@ -191,7 +198,7 @@ static void v8js_v8object_unset_property(zval *object, zval *member, void **cach } V8JS_CTX_PROLOGUE(obj->ctx); - v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); + 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, @@ -199,8 +206,9 @@ static void v8js_v8object_unset_property(zval *object, zval *member, void **cach return; } - if (v8obj->IsObject()) { - v8obj->ToObject(isolate)->Delete(V8JS_SYML(Z_STRVAL_P(member), static_cast(Z_STRLEN_P(member)))); + v8::Local v8obj; + if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) { + v8obj->Delete(v8_context, V8JS_ZSYM(Z_STR_P(member))); } } /* }}} */ @@ -276,9 +284,13 @@ static zend_function *v8js_v8object_get_method(zend_object **object_ptr, zend_st v8::Local v8obj = v8::Local::New(isolate, obj->v8obj); if (!obj->v8obj.IsEmpty() && v8obj->IsObject() && !v8obj->IsFunction()) { - v8::Local jsObj = v8obj->ToObject(isolate); - - if (jsObj->Has(jsKey) && jsObj->Get(jsKey)->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)); f->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY; f->common.function_name = zend_string_copy(method); @@ -324,16 +336,22 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value](v8::Isolate *isolate) { int i = 0; - v8::Local context = v8::Local::New(isolate, obj->ctx->context); + v8::Local v8_context = isolate->GetEnteredContext(); v8::Local method_name = V8JS_SYML(ZSTR_VAL(method), static_cast(ZSTR_LEN(method))); - v8::Local v8obj = v8::Local::New(isolate, obj->v8obj)->ToObject(isolate); + v8::Local v8obj = v8::Local::New(isolate, obj->v8obj)->ToObject(v8_context).ToLocalChecked(); v8::Local thisObj; v8::Local cb; - if (method_name->Equals(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 { - cb = v8::Local::Cast(v8obj->Get(method_name)); + 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 @@ -352,13 +370,13 @@ static int v8js_v8object_call_method(zend_string *method, zend_object *object, I jsArgv[i] = v8::Local::New(isolate, zval_to_v8js(&argv[i], isolate)); } - v8::Local result = cb->Call(thisObj, argc, jsArgv); + v8::MaybeLocal result = cb->Call(v8_context, thisObj, argc, jsArgv); - if (obj->std.ce == php_ce_v8object && result->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); - result.Clear(); + result = v8::MaybeLocal(); } return result; @@ -547,26 +565,28 @@ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */ * some memory on bailout. */ { std::function< v8::MaybeLocal(v8::Isolate *) > v8_call = [g](v8::Isolate *isolate) { - v8::Local method_name = V8JS_STR("next"); - v8::Local v8obj = v8::Local::New(isolate, g->v8obj.v8obj)->ToObject(isolate); - v8::Local cb = v8::Local::Cast(v8obj->Get(method_name));; + v8::Local v8_context = isolate->GetEnteredContext(); + 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 result = cb->Call(v8obj, 0, NULL); + v8::MaybeLocal result = cb->Call(v8_context, v8obj, 0, NULL); if(result.IsEmpty()) { /* cb->Call probably threw (and already threw a zend exception), just return */ return V8JS_NULL; } - if(!result->IsObject()) { + if(!result.ToLocalChecked()->IsObject()) { zend_throw_exception(php_ce_v8js_exception, "V8Generator returned non-object on next()", 0); return V8JS_NULL; } - v8::Local resultObj = result->ToObject(isolate); - v8::Local val = resultObj->Get(V8JS_STR("value")); - v8::Local done = resultObj->Get(V8JS_STR("done")); + + 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(); zval_ptr_dtor(&g->value); v8js_to_zval(val, &g->value, 0, isolate); From 7d560878c9692d4624e6f7c6937d06ef620647dd Mon Sep 17 00:00:00 2001 From: Jan-E Date: Fri, 14 Sep 2018 11:23:19 +0200 Subject: [PATCH 06/13] Update to V8-7.0.276.11-vc15 --- appveyor.yml | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2d65c50..59fd1f5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,22 +2,22 @@ environment: matrix: - ARTIFACT_NAME: v8js_vc15_php-7.3_%Platform%_ts.zip OUTDIR: Release_TS - V8_ASSETS: V8-5.8.283.31-%Platform%.zip - PHP_VERSION: 7.3.0alpha3 + V8_ASSETS: V8-7.0.276.11-vc15-%Platform%.zip + PHP_VERSION: 7.3.0RC1 - ARTIFACT_NAME: v8js_vc15_php-7.3_%Platform%_nts.zip OUTDIR: Release CONFIGURE_EXTRA: --disable-zts - V8_ASSETS: V8-5.8.283.31-%Platform%.zip - PHP_VERSION: 7.3.0alpha3 + V8_ASSETS: V8-7.0.276.11-vc15-%Platform%.zip + PHP_VERSION: 7.3.0RC1 - ARTIFACT_NAME: v8js_vc15_php-7.2_%Platform%_ts.zip OUTDIR: Release_TS - V8_ASSETS: V8-5.8.283.31-%Platform%.zip - PHP_VERSION: 7.2.7 + V8_ASSETS: V8-7.0.276.11-vc15-%Platform%.zip + PHP_VERSION: 7.2.10 - ARTIFACT_NAME: v8js_vc15_php-7.2_%Platform%_nts.zip OUTDIR: Release CONFIGURE_EXTRA: --disable-zts - V8_ASSETS: V8-5.8.283.31-%Platform%.zip - PHP_VERSION: 7.2.7 + V8_ASSETS: V8-7.0.276.11-vc15-%Platform%.zip + PHP_VERSION: 7.2.10 PHP_SDK: c:\projects\php-sdk @@ -30,21 +30,18 @@ platform: install: - cd %PHP_SDK% - - curl -fSL -o php-sdk-2.1.7beta1.zip "https://github.com/Microsoft/php-sdk-binary-tools/archive/php-sdk-2.1.7beta1.zip" - - 7z.exe x php-sdk-2.1.7beta1.zip - - move /y php-sdk-binary-tools-php-sdk-2.1.7beta1\* . - - for /R /D %%f in (php-sdk-binary-tools-php-sdk-2.1.7beta1\*) do move /y %%f . + - curl -fSL -o php-sdk-2.1.9beta1.zip "https://github.com/Microsoft/php-sdk-binary-tools/archive/php-sdk-2.1.9beta1.zip" + - 7z.exe x php-sdk-2.1.9beta1.zip + - move /y php-sdk-binary-tools-php-sdk-2.1.9beta1\* . + - for /R /D %%f in (php-sdk-binary-tools-php-sdk-2.1.9beta1\*) do move /y %%f . - call bin\phpsdk_setvars.bat - call bin\phpsdk_buildtree.bat v8js-ci - cd v8js-ci\vc15\%Platform% - md deps - cd deps - - curl -fSL -o %V8_ASSETS% "https://s3.amazonaws.com/win-phpv8/%V8_ASSETS%" + - curl -fSL -o %V8_ASSETS% "https://phpdev.toolsforresearch.com/%V8_ASSETS%" - 7z.exe x %V8_ASSETS% - - curl -fSL -o libiconv.zip "https://windows.php.net/downloads/php-sdk/deps/vc14/%Platform%/libiconv-1.15-vc14-%Platform%.zip" - - 7z.exe x libiconv.zip -y - - curl -fSL -o libxml2.zip "https://windows.php.net/downloads/php-sdk/deps/vc14/%Platform%/libxml2-2.9.8-vc14-%Platform%.zip" - - 7z.exe x libxml2.zip -y + - dir - cd .. - curl -fSL -o "php-%PHP_VERSION%.tar.gz" "https://github.com/php/php-src/archive/php-%PHP_VERSION%.tar.gz" - ren php php-src-php-%PHP_VERSION% @@ -72,7 +69,7 @@ build_script: - echo Building PHP [%PHP_VERSION%] - '%PHP_SDK%\bin\phpsdk_setvars' - buildconf - - configure --disable-all --enable-cli --with-iconv=yes --with-libxml=yes --with-dom=yes --enable-json=static --with-v8js %CONFIGURE_EXTRA% + - configure --disable-all --enable-cli --with-v8js %CONFIGURE_EXTRA% - nmake after_build: From 8a1803f9b0ac5230212bd27f8d90a50555a0f403 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Fri, 14 Sep 2018 14:03:42 +0200 Subject: [PATCH 07/13] V8 >= 6.9 required --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 00d51de..ed15fc6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Minimum requirements V8 is written in C++ and is used in Google Chrome, the open source browser from Google. V8 implements ECMAScript as specified in ECMA-262, 5th edition. - This extension requires V8 4.6.76 or higher. + This extension requires V8 6.9 (6.9.427.18 is known to work) or higher. V8 releases are published rather quickly and the V8 team usually provides security support for the version line shipped with the Chrome browser (stable channel) and newer (only). @@ -81,7 +81,6 @@ class V8Js /** * Initializes and starts V8 engine and returns new V8Js object with it's own V8 context. - * Snapshots are supported by V8 4.3.7 and higher. * @param string $object_name * @param array $variables * @param array $extensions From 6fcc383c3ce977706ec98be44e2604c445e240bf Mon Sep 17 00:00:00 2001 From: Jan-E Date: Fri, 14 Sep 2018 14:58:20 +0200 Subject: [PATCH 08/13] reintroduce iconv xml dom json-static --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 59fd1f5..920792d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -42,6 +42,10 @@ install: - curl -fSL -o %V8_ASSETS% "https://phpdev.toolsforresearch.com/%V8_ASSETS%" - 7z.exe x %V8_ASSETS% - dir + - curl -fSL -o libiconv.zip "https://windows.php.net/downloads/php-sdk/deps/vc15/%Platform%/libiconv-1.15-3-vc15-%Platform%.zip" + - 7z.exe x libiconv.zip -y + - curl -fSL -o libxml2.zip "https://windows.php.net/downloads/php-sdk/deps/vc15/%Platform%/libxml2-2.9.8-vc15-%Platform%.zip" + - 7z.exe x libxml2.zip -y - cd .. - curl -fSL -o "php-%PHP_VERSION%.tar.gz" "https://github.com/php/php-src/archive/php-%PHP_VERSION%.tar.gz" - ren php php-src-php-%PHP_VERSION% @@ -69,7 +73,7 @@ build_script: - echo Building PHP [%PHP_VERSION%] - '%PHP_SDK%\bin\phpsdk_setvars' - buildconf - - configure --disable-all --enable-cli --with-v8js %CONFIGURE_EXTRA% + - configure --disable-all --enable-cli --with-iconv=yes --with-libxml=yes --with-dom=yes --enable-json=static --with-v8js %CONFIGURE_EXTRA% - nmake after_build: From a67253477bcec84ce09f98650f9d505b52b946e4 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Tue, 6 Nov 2018 12:02:25 +0100 Subject: [PATCH 09/13] disable timezones.phpt test, currently known broken, refs #378 --- tests/timezones.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/timezones.phpt b/tests/timezones.phpt index 74b6f8d..1d22001 100644 --- a/tests/timezones.phpt +++ b/tests/timezones.phpt @@ -1,6 +1,8 @@ --TEST-- Test V8::executeString() : Check timezone handling --SKIPIF-- +SKIP test currently broken, see #378 + Date: Tue, 6 Nov 2018 12:04:55 +0100 Subject: [PATCH 10/13] use ppa:stesie/libv8, build against V8 7.1 --- .travis.yml | 6 +++--- Dockerfile.travis | 2 +- Makefile.travis | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 34ef924..dd2294a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,11 @@ services: - docker env: - - V8VER=6.6 + - V8VER=7.1 PHPVER=7.0 - - V8VER=6.6 + - V8VER=7.1 PHPVER=7.1 - - V8VER=6.6 + - V8VER=7.1 PHPVER=7.2 script: make -f Makefile.travis test diff --git a/Dockerfile.travis b/Dockerfile.travis index 8f89caf..5ce3399 100644 --- a/Dockerfile.travis +++ b/Dockerfile.travis @@ -9,7 +9,7 @@ RUN apt-get update -q RUN apt-get install -y software-properties-common RUN add-apt-repository ppa:ondrej/php -RUN add-apt-repository ppa:pinepain/php -y +RUN add-apt-repository ppa:stesie/libv8 -y RUN apt-get update -q RUN apt-get install -y php$PHPVER-dev libv8-$V8VER-dev diff --git a/Makefile.travis b/Makefile.travis index 2a70252..eb5c42b 100644 --- a/Makefile.travis +++ b/Makefile.travis @@ -1,5 +1,5 @@ # Configure and build scripts for travis CI system -V8VER ?= 6.6 +V8VER ?= 7.1 IMAGENAME ?= v8js-test From e3e3cd53d65f7bc04a9c5a9b784a5a6a790e7098 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Tue, 6 Nov 2018 12:12:36 +0100 Subject: [PATCH 11/13] Update PPA ref --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ed15fc6..57ddeb6 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,9 @@ For some very first steps, instead of compiling manually you might want to try o image](https://registry.hub.docker.com/u/stesie/v8js/). It has v8, v8js and php-cli pre-installed so you can give it a try with PHP in "interactive mode". There is no Apache, etc. running however. -For Ubuntu @pinepain has PPAs for [various versions of V8](https://launchpad.net/~pinepain). +For Ubuntu @stesie has a PPA, based on prior work by @pinepain. +[See here](https://launchpad.net/~stesie/+archive/ubuntu/libv8/), packaging sources are available +[from ppa-packaging repository](https://github.com/phpv8/ppa-packaging/tree/stesie/) (*stesie* branch). You might want to install these and compile V8Js based on them. There also is a Heroku extension pack that has recent V8Js versions for PHP 7.x, see From d2a873f99dda3cb317e9fbdafd617c39ea0c6c7c Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Tue, 6 Nov 2018 13:17:49 +0100 Subject: [PATCH 12/13] define box based on ppa:stesie/libv8 --- Vagrantfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index d998dad..346e81d 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -19,7 +19,7 @@ Vagrant.configure("2") do |config| # # mass-define "generic" Ubuntu boxes # - %w{6.3 6.4 6.5}.each { |version| + %w{7.1}.each { |version| config.vm.define "v8-#{version}" do |i| i.vm.synced_folder ".", "/data/v8js" @@ -31,7 +31,7 @@ Vagrant.configure("2") do |config| apt-get install -y software-properties-common gdb tmux git tig curl apache2-utils lcov add-apt-repository ppa:ondrej/php - add-apt-repository ppa:pinepain/libv8-#{version} + add-apt-repository ppa:stesie/libv8 apt-get update apt-get install -y php7.1-dev libv8-#{version}-dbg libv8-#{version}-dev SHELL From dea7395e57a9224695858189197a05760a11873d Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Tue, 6 Nov 2018 13:20:30 +0100 Subject: [PATCH 13/13] set v8 version accordingly --- config.w32 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.w32 b/config.w32 index bb5af14..bb7ea35 100644 --- a/config.w32 +++ b/config.w32 @@ -15,10 +15,10 @@ if (PHP_V8JS != "no") { ADD_FLAG("CFLAGS_V8JS", "/D __STDC_LIMIT_MACROS"); // defaults - var v8major = 5; - var v8minor = 8; - var v8build = 301; - var v8patch = 0; + var v8major = 7; + var v8minor = 0; + var v8build = 276; + var v8patch = 11; var v8pinc = search_paths("v8-version.h", php_usual_include_suspects, null); if (typeof(v8pinc) == "string") { var v8versionh = file_get_contents(v8pinc + '\\v8-version.h');