diff --git a/php_v8js_macros.h b/php_v8js_macros.h index 3910149..6345df4 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 b55a313..d92b8a7 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 8c34981..77d0857 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 9f824bf..67988e4 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 d0745c7..b376f49 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 aea7438..5d7c6e2 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 2baa16e..22e6b42 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 {