From 4fea8f4fb95d8ed535258030d03e932e7f3d4169 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Wed, 11 May 2016 16:50:37 +0200 Subject: [PATCH 1/5] Require V8 4.6.76 or higher ... and hence remove all #ifdef hell. Those versions didn't have security support by Google anyhow, and it helps to drastically shrink the test matrix. --- README.md | 3 +- config.m4 | 225 ++++++++++++++++++++++------------------------ php_v8js_macros.h | 2 - v8js.cc | 2 - v8js_class.cc | 23 +---- v8js_class.h | 2 - v8js_v8.cc | 46 +--------- 7 files changed, 111 insertions(+), 192 deletions(-) diff --git a/README.md b/README.md index e4091737..e096bd53 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ Minimum requirements V8 is Google's open source Javascript engine. 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 makes use of V8 isolates to ensure separation between multiple V8Js instances and uses the new isolate-based mechanism to throw exceptions, hence the need for 3.24.6 or above. + + This extension requires V8 4.6.76 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). diff --git a/config.m4 b/config.m4 index 63a86f42..bcd35c80 100644 --- a/config.m4 +++ b/config.m4 @@ -121,8 +121,8 @@ int main () set $ac_cv_v8_version IFS=$ac_IFS V8_API_VERSION=`expr [$]1 \* 1000000 + [$]2 \* 1000 + [$]3` - if test "$V8_API_VERSION" -lt 3024006 ; then - AC_MSG_ERROR([libv8 must be version 3.24.6 or greater]) + if test "$V8_API_VERSION" -lt 4006076 ; then + AC_MSG_ERROR([libv8 must be version 4.6.76 or greater]) fi AC_DEFINE_UNQUOTED([PHP_V8_API_VERSION], $V8_API_VERSION, [ ]) AC_DEFINE_UNQUOTED([PHP_V8_VERSION], "$ac_cv_v8_version", [ ]) @@ -130,129 +130,116 @@ int main () AC_MSG_ERROR([could not determine libv8 version]) fi - if test "$V8_API_VERSION" -ge 3029036 ; then - dnl building for v8 3.29.36 or later, which requires us to - dnl initialize and provide a platform; hence we need to - dnl link in libplatform to make our life easier. - PHP_ADD_INCLUDE($V8_DIR) + PHP_ADD_INCLUDE($V8_DIR) - case $host_os in - darwin* ) - static_link_extra="libv8_libplatform.a libv8_libbase.a" - ;; - * ) - static_link_extra="libv8_libplatform.a" - ;; - esac - - LDFLAGS_libplatform="" - for static_link_extra_file in $static_link_extra; do - AC_MSG_CHECKING([for $static_link_extra_file]) - - for i in $PHP_V8JS $SEARCH_PATH ; do - if test -r $i/lib64/$static_link_extra_file; then - static_link_dir=$i/lib64 - AC_MSG_RESULT(found in $i) - fi - if test -r $i/lib/$static_link_extra_file; then - static_link_dir=$i/lib - AC_MSG_RESULT(found in $i) - fi - done - - if test -z "$static_link_dir"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([Please provide $static_link_extra_file next to the libv8.so, see README.md for details]) - fi - - LDFLAGS_libplatform="$LDFLAGS_libplatform $static_link_dir/$static_link_extra_file" - done + case $host_os in + darwin* ) + static_link_extra="libv8_libplatform.a libv8_libbase.a" + ;; + * ) + static_link_extra="libv8_libplatform.a" + ;; + esac - # modify flags for (possibly) succeeding V8 startup check - CPPFLAGS="$CPPFLAGS -I$V8_DIR" - LIBS="$LIBS $LDFLAGS_libplatform" - fi + LDFLAGS_libplatform="" + for static_link_extra_file in $static_link_extra; do + AC_MSG_CHECKING([for $static_link_extra_file]) + + for i in $PHP_V8JS $SEARCH_PATH ; do + if test -r $i/lib64/$static_link_extra_file; then + static_link_dir=$i/lib64 + AC_MSG_RESULT(found in $i) + fi + if test -r $i/lib/$static_link_extra_file; then + static_link_dir=$i/lib + AC_MSG_RESULT(found in $i) + fi + done + + if test -z "$static_link_dir"; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([Please provide $static_link_extra_file next to the libv8.so, see README.md for details]) + fi + + LDFLAGS_libplatform="$LDFLAGS_libplatform $static_link_dir/$static_link_extra_file" + done + + # modify flags for (possibly) succeeding V8 startup check + CPPFLAGS="$CPPFLAGS -I$V8_DIR" + LIBS="$LIBS $LDFLAGS_libplatform" + + dnl building for v8 4.4.10 or later, which requires us to + dnl provide startup data, if V8 wasn't compiled with snapshot=off. + AC_MSG_CHECKING([whether V8 requires startup data]) + AC_TRY_RUN([ + #include + #include + #include + #include - if test "$V8_API_VERSION" -ge 4004010 ; then - dnl building for v8 4.4.10 or later, which requires us to - dnl provide startup data, if V8 wasn't compiled with snapshot=off. - AC_MSG_CHECKING([whether V8 requires startup data]) - AC_TRY_RUN([ - #include - #include - #include - #include - -#if PHP_V8_API_VERSION >= 4004010 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { public: - virtual void* Allocate(size_t length) { - void* data = AllocateUninitialized(length); - return data == NULL ? data : memset(data, 0, length); - } - virtual void* AllocateUninitialized(size_t length) { return malloc(length); } - virtual void Free(void* data, size_t) { free(data); } + virtual void* Allocate(size_t length) { + void* data = AllocateUninitialized(length); + return data == NULL ? data : memset(data, 0, length); + } + virtual void* AllocateUninitialized(size_t length) { return malloc(length); } + virtual void Free(void* data, size_t) { free(data); } }; -#endif - - int main () - { - v8::Platform *v8_platform = v8::platform::CreateDefaultPlatform(); - v8::V8::InitializePlatform(v8_platform); - v8::V8::Initialize(); - -#if PHP_V8_API_VERSION >= 4004044 - static ArrayBufferAllocator array_buffer_allocator; - v8::Isolate::CreateParams create_params; - create_params.array_buffer_allocator = &array_buffer_allocator; - - v8::Isolate::New(create_params); -#else /* PHP_V8_API_VERSION < 4004044 */ - v8::Isolate::New(); -#endif - return 0; - } - ], [ - AC_MSG_RESULT([no]) - ], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([PHP_V8_USE_EXTERNAL_STARTUP_DATA], [1], [Whether V8 requires (and can be provided with custom versions of) external startup data]) - - SEARCH_PATH="$V8_DIR/lib $V8_DIR/share/v8" - - AC_MSG_CHECKING([for natives_blob.bin]) - SEARCH_FOR="natives_blob.bin" - - for i in $SEARCH_PATH ; do - if test -r $i/$SEARCH_FOR; then - AC_MSG_RESULT([found ($i/$SEARCH_FOR)]) - AC_DEFINE_UNQUOTED([PHP_V8_NATIVES_BLOB_PATH], "$i/$SEARCH_FOR", [Full path to natives_blob.bin file]) - native_blob_found=1 - fi - done - - if test -z "$native_blob_found"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([Please provide V8 native blob as needed]) - fi - - AC_MSG_CHECKING([for snapshot_blob.bin]) - SEARCH_FOR="snapshot_blob.bin" - - for i in $SEARCH_PATH ; do - if test -r $i/$SEARCH_FOR; then - AC_MSG_RESULT([found ($i/$SEARCH_FOR)]) - AC_DEFINE_UNQUOTED([PHP_V8_SNAPSHOT_BLOB_PATH], "$i/$SEARCH_FOR", [Full path to snapshot_blob.bin file]) - snapshot_blob_found=1 - fi - done - - if test -z "$snapshot_blob_found"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([Please provide V8 snapshot blob as needed]) - fi - ]) - fi + + int main () + { + v8::Platform *v8_platform = v8::platform::CreateDefaultPlatform(); + v8::V8::InitializePlatform(v8_platform); + v8::V8::Initialize(); + + static ArrayBufferAllocator array_buffer_allocator; + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = &array_buffer_allocator; + + v8::Isolate::New(create_params); + return 0; + } + ], [ + AC_MSG_RESULT([no]) + ], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([PHP_V8_USE_EXTERNAL_STARTUP_DATA], [1], [Whether V8 requires (and can be provided with custom versions of) external startup data]) + + SEARCH_PATH="$V8_DIR/lib $V8_DIR/share/v8" + + AC_MSG_CHECKING([for natives_blob.bin]) + SEARCH_FOR="natives_blob.bin" + + for i in $SEARCH_PATH ; do + if test -r $i/$SEARCH_FOR; then + AC_MSG_RESULT([found ($i/$SEARCH_FOR)]) + AC_DEFINE_UNQUOTED([PHP_V8_NATIVES_BLOB_PATH], "$i/$SEARCH_FOR", [Full path to natives_blob.bin file]) + native_blob_found=1 + fi + done + + if test -z "$native_blob_found"; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([Please provide V8 native blob as needed]) + fi + + AC_MSG_CHECKING([for snapshot_blob.bin]) + SEARCH_FOR="snapshot_blob.bin" + + for i in $SEARCH_PATH ; do + if test -r $i/$SEARCH_FOR; then + AC_MSG_RESULT([found ($i/$SEARCH_FOR)]) + AC_DEFINE_UNQUOTED([PHP_V8_SNAPSHOT_BLOB_PATH], "$i/$SEARCH_FOR", [Full path to snapshot_blob.bin file]) + snapshot_blob_found=1 + fi + done + + if test -z "$snapshot_blob_found"; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([Please provide V8 snapshot blob as needed]) + fi + ]) AC_LANG_RESTORE LIBS=$old_LIBS diff --git a/php_v8js_macros.h b/php_v8js_macros.h index a965651e..3910149f 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -167,9 +167,7 @@ struct _v8js_process_globals { /* V8 command line flags */ char *v8_flags; -#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036 v8::Platform *v8_platform; -#endif }; extern struct _v8js_process_globals v8js_process_globals; diff --git a/v8js.cc b/v8js.cc index 272ce874..4b6302d9 100755 --- a/v8js.cc +++ b/v8js.cc @@ -150,11 +150,9 @@ static PHP_MSHUTDOWN_FUNCTION(v8js) if(v8_initialized) { v8::V8::Dispose(); -#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036 v8::V8::ShutdownPlatform(); // @fixme call virtual destructor somehow //delete v8js_process_globals.v8_platform; -#endif } if (v8js_process_globals.v8_flags) { diff --git a/v8js_class.cc b/v8js_class.cc index 4d8a6384..2a620ef7 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | http://www.opensource.org/licenses/mit-license.php MIT License | +----------------------------------------------------------------------+ @@ -71,7 +71,6 @@ struct v8js_jsext { }; /* }}} */ -#if PHP_V8_API_VERSION >= 4004010 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { public: virtual void* Allocate(size_t length) { @@ -81,7 +80,6 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { virtual void* AllocateUninitialized(size_t length) { return malloc(length); } virtual void Free(void* data, size_t) { free(data); } }; -#endif static void v8js_free_storage(void *object TSRMLS_DC) /* {{{ */ { @@ -207,11 +205,9 @@ static void v8js_free_storage(void *object TSRMLS_DC) /* {{{ */ c->modules_stack.~vector(); c->modules_base.~vector(); -#if PHP_V8_API_VERSION >= 4003007 if (c->zval_snapshot_blob) { zval_ptr_dtor(&c->zval_snapshot_blob); } -#endif efree(object); } @@ -367,13 +363,10 @@ static PHP_METHOD(V8Js, __construct) c->pending_exception = NULL; c->in_execution = 0; -#if PHP_V8_API_VERSION >= 4003007 new (&c->create_params) v8::Isolate::CreateParams(); -#if PHP_V8_API_VERSION >= 4004044 static ArrayBufferAllocator array_buffer_allocator; c->create_params.array_buffer_allocator = &array_buffer_allocator; -#endif new (&c->snapshot_blob) v8::StartupData(); if (snapshot_blob) { @@ -390,10 +383,6 @@ static PHP_METHOD(V8Js, __construct) } c->isolate = v8::Isolate::New(c->create_params); -#else /* PHP_V8_API_VERSION < 4003007 */ - c->isolate = v8::Isolate::New(); -#endif - c->isolate->SetData(0, c); c->time_limit = 0; @@ -1108,7 +1097,7 @@ static PHP_METHOD(V8Js, getExtensions) } /* }}} */ -#if PHP_V8_API_VERSION >= 4003007 + /* {{{ proto string|bool V8Js::createSnapshot(string embed_source) */ static PHP_METHOD(V8Js, createSnapshot) @@ -1139,7 +1128,6 @@ static PHP_METHOD(V8Js, createSnapshot) delete[] snapshot_blob.data; } /* }}} */ -#endif /* PHP_V8_API_VERSION >= 4003007 */ /* {{{ arginfo */ @@ -1210,11 +1198,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_v8js_getextensions, 0) ZEND_END_ARG_INFO() -#if PHP_V8_API_VERSION >= 4003007 ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_createsnapshot, 0, 0, 1) ZEND_ARG_INFO(0, script) ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_settimelimit, 0, 0, 1) ZEND_ARG_INFO(0, time_limit) @@ -1242,10 +1228,7 @@ const zend_function_entry v8js_methods[] = { /* {{{ */ PHP_ME(V8Js, setAverageObjectSize, arginfo_v8js_setaverageobjectsize, ZEND_ACC_PUBLIC) PHP_ME(V8Js, registerExtension, arginfo_v8js_registerextension, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(V8Js, getExtensions, arginfo_v8js_getextensions, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - -#if PHP_V8_API_VERSION >= 4003007 PHP_ME(V8Js, createSnapshot, arginfo_v8js_createsnapshot, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -#endif {NULL, NULL, NULL} }; /* }}} */ @@ -1314,10 +1297,8 @@ PHP_MINIT_FUNCTION(v8js_class) /* {{{ */ le_v8js_script = zend_register_list_destructors_ex(v8js_script_dtor, NULL, PHP_V8JS_SCRIPT_RES_NAME, module_number); -#if PHP_V8_API_VERSION >= 4004010 && PHP_V8_API_VERSION < 4004044 static ArrayBufferAllocator array_buffer_allocator; v8::V8::SetArrayBufferAllocator(&array_buffer_allocator); -#endif return SUCCESS; } /* }}} */ diff --git a/v8js_class.h b/v8js_class.h index f4edeb5f..00f4539b 100644 --- a/v8js_class.h +++ b/v8js_class.h @@ -70,11 +70,9 @@ struct v8js_ctx { std::vector script_objects; char *tz; -#if PHP_V8_API_VERSION >= 4003007 v8::Isolate::CreateParams create_params; zval *zval_snapshot_blob; v8::StartupData snapshot_blob; -#endif #ifdef ZTS void ***zts_ctx; diff --git a/v8js_v8.cc b/v8js_v8.cc index 8d536650..2baa16e3 100644 --- a/v8js_v8.cc +++ b/v8js_v8.cc @@ -25,7 +25,7 @@ extern "C" { #include "zend_exceptions.h" } -#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036 +#if !defined(_WIN32) #include #endif @@ -34,43 +34,6 @@ extern "C" { #include "v8js_timer.h" #include "v8js_exceptions.h" -#if defined(PHP_V8_USE_EXTERNAL_STARTUP_DATA) && PHP_V8_API_VERSION < 4006076 -/* Old V8 version, requires startup data but has no - * (internal/API) means to let it be loaded. */ -static v8::StartupData natives_; -static v8::StartupData snapshot_; - -static void v8js_v8_load_startup_data(const char* blob_file, - v8::StartupData* startup_data, - void (*setter_fn)(v8::StartupData*)) { - startup_data->data = NULL; - startup_data->raw_size = 0; - - if (!blob_file) { - return; - } - - FILE* file = fopen(blob_file, "rb"); - if (!file) { - return; - } - - fseek(file, 0, SEEK_END); - startup_data->raw_size = static_cast(ftell(file)); - rewind(file); - - startup_data->data = new char[startup_data->raw_size]; - int read_size = static_cast(fread(const_cast(startup_data->data), - 1, startup_data->raw_size, file)); - fclose(file); - - if (startup_data->raw_size == read_size) { - (*setter_fn)(startup_data); - } -} -#endif - - void v8js_v8_init(TSRMLS_D) /* {{{ */ { /* Run only once; thread-local test first */ @@ -93,21 +56,14 @@ void v8js_v8_init(TSRMLS_D) /* {{{ */ #ifdef PHP_V8_USE_EXTERNAL_STARTUP_DATA /* V8 doesn't work without startup data, load it. */ -#if PHP_V8_API_VERSION >= 4006076 v8::V8::InitializeExternalStartupData( PHP_V8_NATIVES_BLOB_PATH, PHP_V8_SNAPSHOT_BLOB_PATH ); -#else - v8js_v8_load_startup_data(PHP_V8_NATIVES_BLOB_PATH, &natives_, v8::V8::SetNativesDataBlob); - v8js_v8_load_startup_data(PHP_V8_SNAPSHOT_BLOB_PATH, &snapshot_, v8::V8::SetSnapshotDataBlob); -#endif #endif -#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036 v8js_process_globals.v8_platform = v8::platform::CreateDefaultPlatform(); v8::V8::InitializePlatform(v8js_process_globals.v8_platform); -#endif /* Set V8 command line flags (must be done before V8::Initialize()!) */ if (v8js_process_globals.v8_flags) { From ed8e88e11d35e7bd3571c46a8797c2e93232b9ed Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sun, 22 May 2016 15:11:35 +0200 Subject: [PATCH 2/5] Search libv8_libplatform.a in V8_DIR only Otherwise config.m4 will find another libv8_libplatform.a (e.g. in /usr/lib) as well ... and then use the wrong one. --- config.m4 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/config.m4 b/config.m4 index bcd35c80..694fca9d 100644 --- a/config.m4 +++ b/config.m4 @@ -145,16 +145,15 @@ int main () for static_link_extra_file in $static_link_extra; do AC_MSG_CHECKING([for $static_link_extra_file]) - for i in $PHP_V8JS $SEARCH_PATH ; do - if test -r $i/lib64/$static_link_extra_file; then - static_link_dir=$i/lib64 - AC_MSG_RESULT(found in $i) - fi - if test -r $i/lib/$static_link_extra_file; then - static_link_dir=$i/lib - AC_MSG_RESULT(found in $i) - fi - done + if test -r $V8_DIR/lib64/$static_link_extra_file; then + static_link_dir=$V8_DIR/lib64 + AC_MSG_RESULT(found in $V8_DIR/lib64) + fi + + if test -r $V8_DIR/lib/$static_link_extra_file; then + static_link_dir=$V8_DIR/lib + AC_MSG_RESULT(found in $V8_DIR/lib) + fi if test -z "$static_link_dir"; then AC_MSG_RESULT([not found]) From d4d8ccc4f6ee7db37286f8deb71681d14d82f0a0 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sun, 22 May 2016 15:20:05 +0200 Subject: [PATCH 3/5] Fix #ifdef change, don't call SetArrayBufferAllocator --- v8js_class.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/v8js_class.cc b/v8js_class.cc index 2a620ef7..8c349814 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -1297,9 +1297,6 @@ PHP_MINIT_FUNCTION(v8js_class) /* {{{ */ le_v8js_script = zend_register_list_destructors_ex(v8js_script_dtor, NULL, PHP_V8JS_SCRIPT_RES_NAME, module_number); - static ArrayBufferAllocator array_buffer_allocator; - v8::V8::SetArrayBufferAllocator(&array_buffer_allocator); - return SUCCESS; } /* }}} */ From 05b96a96b8d44d9d859b12c557d5eddd0b34beba Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sun, 22 May 2016 15:12:44 +0200 Subject: [PATCH 4/5] Use internal fields instead of GetHiddenValue/SetHiddenValue The latter were deprecated and removed in V8 5.2 --- php_v8js_macros.h | 3 --- v8js_array_access.cc | 20 +++++++------------- v8js_class.cc | 3 ++- v8js_convert.cc | 12 +++++++----- v8js_exceptions.cc | 19 +++++++------------ v8js_object_export.cc | 30 ++++++++++++------------------ v8js_v8.cc | 9 ++------- 7 files changed, 37 insertions(+), 59 deletions(-) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index 3910149f..6345df45 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -55,9 +55,6 @@ extern "C" { /* V8Js Version */ #define PHP_V8JS_VERSION "0.6.2" -/* Hidden field name used to link JS wrappers with underlying PHP object */ -#define PHPJS_OBJECT_KEY "phpjs::object" - /* Helper macros */ #define V8JS_GET_CLASS_NAME(var, obj) \ v8::String::Utf8Value var(obj->GetConstructorName()); diff --git a/v8js_array_access.cc b/v8js_array_access.cc index b55a313c..d92b8a70 100644 --- a/v8js_array_access.cc +++ b/v8js_array_access.cc @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | http://www.opensource.org/licenses/mit-license.php MIT License | +----------------------------------------------------------------------+ @@ -73,8 +73,7 @@ void v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); zval *php_value = v8js_array_access_dispatch(object, "offsetGet", 1, index, NULL TSRMLS_CC); v8::Local ret_value = zval_to_v8js(php_value, isolate TSRMLS_CC); @@ -92,8 +91,7 @@ void v8js_array_access_setter(uint32_t index, v8::Local value, V8JS_TSRMLS_FETCH(); - v8::Local php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); zval *zvalue_ptr; MAKE_STD_ZVAL(zvalue_ptr); @@ -156,8 +154,7 @@ static void v8js_array_access_length(v8::Local property, const v8::P V8JS_TSRMLS_FETCH(); - v8::Local php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); int length = v8js_array_access_get_count_result(object TSRMLS_CC); info.GetReturnValue().Set(V8JS_INT(length)); @@ -171,8 +168,7 @@ void v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); zval *php_value = v8js_array_access_dispatch(object, "offsetUnset", 1, index, NULL TSRMLS_CC); zval_ptr_dtor(&php_value); @@ -188,8 +184,7 @@ void v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); /* If index is set, then return an integer encoding a v8::PropertyAttribute; * otherwise we're expected to return an empty handle. */ @@ -207,8 +202,7 @@ void v8js_array_access_enumerator(const v8::PropertyCallbackInfo& inf V8JS_TSRMLS_FETCH(); - v8::Local php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); int length = v8js_array_access_get_count_result(object TSRMLS_CC); v8::Local result = v8::Array::New(isolate, length); diff --git a/v8js_class.cc b/v8js_class.cc index 8c349814..77d0857b 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -475,6 +475,7 @@ static PHP_METHOD(V8Js, __construct) c->object_name.Reset(isolate, object_name_js); /* Add the PHP object into global object */ + php_obj_t->InstanceTemplate()->SetInternalFieldCount(2); v8::Local php_obj = php_obj_t->InstanceTemplate()->NewInstance(); V8JS_GLOBAL(isolate)->ForceSet(object_name_js, php_obj, v8::ReadOnly); @@ -505,7 +506,7 @@ static PHP_METHOD(V8Js, __construct) } /* Add pointer to zend object */ - php_obj->SetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY), v8::External::New(isolate, getThis())); + php_obj->SetAlignedPointerInInternalField(1, getThis()); /* Export public methods */ zend_function *method_ptr; diff --git a/v8js_convert.cc b/v8js_convert.cc index 9f824bf1..67988e41 100644 --- a/v8js_convert.cc +++ b/v8js_convert.cc @@ -2,12 +2,13 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | http://www.opensource.org/licenses/mit-license.php MIT License | +----------------------------------------------------------------------+ | Author: Jani Taskinen | | Author: Patrick Reilly | + | Author: Stefan Siegl | +----------------------------------------------------------------------+ */ @@ -236,14 +237,15 @@ int v8js_to_zval(v8::Handle jsValue, zval *return_value, int flags, v } else if (jsValue->IsObject()) { - v8::Handle self = v8::Handle::Cast(jsValue); + v8::Local self = jsValue->ToObject(); + // if this is a wrapped PHP object, then just unwrap it. - v8::Local php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - if (!php_object.IsEmpty()) { - zval *object = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + if (self->InternalFieldCount()) { + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); RETVAL_ZVAL(object, 1, 0); return SUCCESS; } + if ((flags & V8JS_FLAG_FORCE_ARRAY && !jsValue->IsFunction()) || jsValue->IsArray()) { array_init(return_value); return v8js_get_properties_hash(jsValue, Z_ARRVAL_P(return_value), flags, isolate TSRMLS_CC); diff --git a/v8js_exceptions.cc b/v8js_exceptions.cc index d0745c70..b376f495 100644 --- a/v8js_exceptions.cc +++ b/v8js_exceptions.cc @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | http://www.opensource.org/licenses/mit-license.php MIT License | +----------------------------------------------------------------------+ @@ -83,18 +83,13 @@ void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8:: PHPV8_EXPROP(_string, JsTrace, stacktrace_string); } - if(try_catch->Exception()->IsObject()) { - v8::Local php_ref = try_catch->Exception()->ToObject()->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); + if(try_catch->Exception()->IsObject() && try_catch->Exception()->ToObject()->InternalFieldCount()) { + zval *php_exception = reinterpret_cast(try_catch->Exception()->ToObject()->GetAlignedPointerFromInternalField(1)); - if(!php_ref.IsEmpty()) { - assert(php_ref->IsExternal()); - zval *php_exception = reinterpret_cast(v8::External::Cast(*php_ref)->Value()); - - zend_class_entry *exception_ce = zend_exception_get_default(TSRMLS_C); - if (Z_TYPE_P(php_exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(php_exception), exception_ce TSRMLS_CC)) { - Z_ADDREF_P(php_exception); - zend_exception_set_previous(return_value, php_exception TSRMLS_CC); - } + zend_class_entry *exception_ce = zend_exception_get_default(TSRMLS_C); + if (Z_TYPE_P(php_exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(php_exception), exception_ce TSRMLS_CC)) { + Z_ADDREF_P(php_exception); + zend_exception_set_previous(return_value, php_exception TSRMLS_CC); } } diff --git a/v8js_object_export.cc b/v8js_object_export.cc index aea7438d..5d7c6e25 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -2,12 +2,13 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | http://www.opensource.org/licenses/mit-license.php MIT License | +----------------------------------------------------------------------+ | Author: Jani Taskinen | | Author: Patrick Reilly | + | Author: Stefan Siegl | +----------------------------------------------------------------------+ */ @@ -88,13 +89,9 @@ static void v8js_call_php_func(zval *value, zend_class_entry *ce, zend_function fci.params = (zval ***) safe_emalloc(argc, sizeof(zval **), 0); argv = (zval **) safe_emalloc(argc, sizeof(zval *), 0); for (i = 0; i < argc; i++) { - v8::Local php_object; - if (info[i]->IsObject()) { - php_object = v8::Local::Cast(info[i])->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - } - if (!php_object.IsEmpty()) { + if (info[i]->IsObject() && info[i]->ToObject()->InternalFieldCount()) { /* This is a PHP object, passed to JS and back. */ - argv[i] = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + argv[i] = reinterpret_cast(info[i]->ToObject()->GetAlignedPointerFromInternalField(1)); Z_ADDREF_P(argv[i]); } else { MAKE_STD_ZVAL(argv[i]); @@ -178,7 +175,7 @@ void v8js_php_callback(const v8::FunctionCallbackInfo& info) /* {{{ * v8::Local self = info.Holder(); V8JS_TSRMLS_FETCH(); - zval *value = reinterpret_cast(v8::External::Cast(*self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)))->Value()); + zval *value = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); zend_function *method_ptr; zend_class_entry *ce = Z_OBJCE_P(value); @@ -198,9 +195,7 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i v8::Isolate *isolate = info.GetIsolate(); info.GetReturnValue().Set(V8JS_UNDEFINED); - // @todo assert constructor call v8::Handle newobj = info.This(); - v8::Local php_object; zval *value; if (!info.IsConstructCall()) { @@ -215,14 +210,14 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i if (info[0]->IsExternal()) { // Object created by v8js in v8js_hash_to_jsobj, PHP object passed as v8::External. - php_object = v8::Local::Cast(info[0]); + v8::Local php_object = v8::Local::Cast(info[0]); value = reinterpret_cast(php_object->Value()); if(ctx->weak_objects.count(value)) { // We already exported this object, hence no need to add another // ref, v8 won't give us a second weak-object callback anyways. newobj->SetAlignedPointerInInternalField(0, ext_tmpl->Value()); - newobj->SetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY), php_object); + newobj->SetAlignedPointerInInternalField(1, value); return; } @@ -248,11 +243,10 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i if (ctor_ptr != NULL) { v8js_call_php_func(value, ce, ctor_ptr, isolate, info TSRMLS_CC); } - php_object = v8::External::New(isolate, value); } newobj->SetAlignedPointerInInternalField(0, ext_tmpl->Value()); - newobj->SetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY), php_object); + newobj->SetAlignedPointerInInternalField(1, value); // Since we got to decrease the reference count again, in case v8 garbage collector // decides to dispose the JS object, we add a weak persistent handle and register @@ -319,7 +313,7 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo(v8::External::Cast(*self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)))->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); ce = Z_OBJCE_P(object); /* enumerate all methods */ @@ -449,7 +443,7 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo& info) V8JS_TSRMLS_FETCH(); zend_class_entry *ce; - zval *object = reinterpret_cast(v8::External::Cast(*self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)))->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); ce = Z_OBJCE_P(object); // first arg is method name, second arg is array of args. @@ -541,7 +535,7 @@ inline v8::Local v8js_named_property_callback(v8::Local p zend_function *method_ptr = NULL; zval *php_value; - zval *object = reinterpret_cast(v8::External::Cast(*self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)))->Value()); + zval *object = reinterpret_cast(self->GetAlignedPointerFromInternalField(1)); v8js_tmpl_t *tmpl_ptr = reinterpret_cast(self->GetAlignedPointerFromInternalField(0)); v8::Local tmpl = v8::Local::New(isolate, *tmpl_ptr); ce = scope = Z_OBJCE_P(object); @@ -809,7 +803,7 @@ static v8::Handle v8js_wrap_object(v8::Isolate *isolate, zend_class_ new_tpl = v8::FunctionTemplate::New(isolate, 0); new_tpl->SetClassName(V8JS_STRL(ce->name, ce->name_length)); - new_tpl->InstanceTemplate()->SetInternalFieldCount(1); + new_tpl->InstanceTemplate()->SetInternalFieldCount(2); if (ce == zend_ce_closure) { /* Got a closure, mustn't cache ... */ diff --git a/v8js_v8.cc b/v8js_v8.cc index 2baa16e3..22e6b427 100644 --- a/v8js_v8.cc +++ b/v8js_v8.cc @@ -276,13 +276,8 @@ int v8js_get_properties_hash(v8::Handle jsValue, HashTable *retval, i const char *key = ToCString(cstr); zval *value = NULL; - v8::Local php_object; - if (jsVal->IsObject()) { - php_object = v8::Local::Cast(jsVal)->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY)); - } - if (!php_object.IsEmpty()) { - /* This is a PHP object, passed to JS and back. */ - value = reinterpret_cast(v8::External::Cast(*php_object)->Value()); + if (jsVal->IsObject() && jsVal->ToObject()->InternalFieldCount()) { + value = reinterpret_cast(jsVal->ToObject()->GetAlignedPointerFromInternalField(1)); Z_ADDREF_P(value); } else { From ec6c6d3eb3bcd95e134bedb0bb015cc099d854a9 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sun, 22 May 2016 20:08:28 +0200 Subject: [PATCH 5/5] Use WeakCallbackInfo WeakCallbackData was deprecated and finally removed in V8 5.2 --- v8js_object_export.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/v8js_object_export.cc b/v8js_object_export.cc index 5d7c6e25..ef6784af 100644 --- a/v8js_object_export.cc +++ b/v8js_object_export.cc @@ -30,7 +30,7 @@ extern "C" { #include "v8js_object_export.h" #include "v8js_v8object_class.h" -static void v8js_weak_object_callback(const v8::WeakCallbackData &data); +static void v8js_weak_object_callback(const v8::WeakCallbackInfo &data); /* Callback for PHP methods and functions */ static void v8js_call_php_func(zval *value, zend_class_entry *ce, zend_function *method_ptr, v8::Isolate *isolate, const v8::FunctionCallbackInfo& info TSRMLS_DC) /* {{{ */ @@ -252,7 +252,7 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i // decides to dispose the JS object, we add a weak persistent handle and register // a callback function that removes the reference. ctx->weak_objects[value].Reset(isolate, newobj); - ctx->weak_objects[value].SetWeak(value, v8js_weak_object_callback); + ctx->weak_objects[value].SetWeak(value, v8js_weak_object_callback, v8::WeakCallbackType::kParameter); // Just tell v8 that we're allocating some external memory // (for the moment we just always tell 1k instead of trying to find out actual values) @@ -261,7 +261,7 @@ static void v8js_construct_callback(const v8::FunctionCallbackInfo& i /* }}} */ -static void v8js_weak_object_callback(const v8::WeakCallbackData &data) { +static void v8js_weak_object_callback(const v8::WeakCallbackInfo &data) { v8::Isolate *isolate = data.GetIsolate(); zval *value = data.GetParameter(); @@ -275,7 +275,7 @@ static void v8js_weak_object_callback(const v8::WeakCallbackDataAdjustAmountOfExternalAllocatedMemory(-ctx->average_object_size); } -static void v8js_weak_closure_callback(const v8::WeakCallbackData &data) { +static void v8js_weak_closure_callback(const v8::WeakCallbackInfo &data) { v8::Isolate *isolate = data.GetIsolate(); v8js_tmpl_t *persist_tpl_ = data.GetParameter(); @@ -884,7 +884,7 @@ static v8::Handle v8js_wrap_object(v8::Isolate *isolate, zend_class_ if (ce == zend_ce_closure) { // free uncached function template when object is freed ctx->weak_closures[persist_tpl_].Reset(isolate, newobj); - ctx->weak_closures[persist_tpl_].SetWeak(persist_tpl_, v8js_weak_closure_callback); + ctx->weak_closures[persist_tpl_].SetWeak(persist_tpl_, v8js_weak_closure_callback, v8::WeakCallbackType::kParameter); } return newobj;