0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-12-22 14:01:53 +00:00

V8 isolates need to be passed into all variable accessor and conversion functions.

This commit is contained in:
Simon Best 2013-04-14 00:36:05 +01:00
parent 8ae7606338
commit 8d8c671aa0
4 changed files with 61 additions and 45 deletions

View File

@ -92,19 +92,19 @@ extern zend_class_entry *php_ce_v8_object;
extern zend_class_entry *php_ce_v8_function; extern zend_class_entry *php_ce_v8_function;
/* Create PHP V8 object */ /* Create PHP V8 object */
void php_v8js_create_v8(zval *, v8::Handle<v8::Value>, int TSRMLS_DC); void php_v8js_create_v8(zval *, v8::Handle<v8::Value>, int, v8::Isolate * TSRMLS_DC);
/* Fetch V8 object properties */ /* Fetch V8 object properties */
int php_v8js_v8_get_properties_hash(v8::Handle<v8::Value>, HashTable *, int TSRMLS_DC); int php_v8js_v8_get_properties_hash(v8::Handle<v8::Value>, HashTable *, int, v8::Isolate * TSRMLS_DC);
/* Convert zval into V8 value */ /* Convert zval into V8 value */
v8::Handle<v8::Value> zval_to_v8js(zval * TSRMLS_DC); v8::Handle<v8::Value> zval_to_v8js(zval *, v8::Isolate * TSRMLS_DC);
/* Convert V8 value into zval */ /* Convert V8 value into zval */
int v8js_to_zval(v8::Handle<v8::Value>, zval *, int TSRMLS_DC); int v8js_to_zval(v8::Handle<v8::Value>, zval *, int, v8::Isolate * TSRMLS_DC);
/* Register accessors into passed object */ /* Register accessors into passed object */
void php_v8js_register_accessors(v8::Local<v8::ObjectTemplate>, zval * TSRMLS_DC); void php_v8js_register_accessors(v8::Local<v8::ObjectTemplate>, zval *, v8::Isolate * TSRMLS_DC);
/* {{{ Context container */ /* {{{ Context container */
struct php_v8js_ctx { struct php_v8js_ctx {

34
v8js.cc
View File

@ -112,6 +112,7 @@ struct php_v8js_object {
zend_object std; zend_object std;
v8::Persistent<v8::Value> v8obj; v8::Persistent<v8::Value> v8obj;
int flags; int flags;
v8::Isolate *isolate;
}; };
/* }}} */ /* }}} */
@ -147,7 +148,7 @@ static zval *php_v8js_v8_read_property(zval *object, zval *member, int type ZEND
MAKE_STD_ZVAL(retval); MAKE_STD_ZVAL(retval);
} }
if (v8js_to_zval(jsVal, retval, obj->flags TSRMLS_CC) == SUCCESS) { if (v8js_to_zval(jsVal, retval, obj->flags, obj->isolate TSRMLS_CC) == SUCCESS) {
return retval; return retval;
} }
} }
@ -164,7 +165,7 @@ static void php_v8js_v8_write_property(zval *object, zval *member, zval *value Z
php_v8js_object *obj = (php_v8js_object *) zend_object_store_get_object(object TSRMLS_CC); php_v8js_object *obj = (php_v8js_object *) zend_object_store_get_object(object TSRMLS_CC);
if (obj->v8obj->IsObject() && !obj->v8obj->IsFunction()) { if (obj->v8obj->IsObject() && !obj->v8obj->IsFunction()) {
obj->v8obj->ToObject()->ForceSet(V8JS_SYML(Z_STRVAL_P(member), Z_STRLEN_P(member)), zval_to_v8js(value TSRMLS_CC)); obj->v8obj->ToObject()->ForceSet(V8JS_SYML(Z_STRVAL_P(member), Z_STRLEN_P(member)), zval_to_v8js(value, obj->isolate TSRMLS_CC));
} }
} }
/* }}} */ /* }}} */
@ -179,7 +180,7 @@ static void php_v8js_v8_unset_property(zval *object, zval *member ZEND_HASH_KEY_
} }
/* }}} */ /* }}} */
int php_v8js_v8_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *retval, int flags TSRMLS_DC) /* {{{ */ int php_v8js_v8_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *retval, int flags, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
v8::Local<v8::Object> jsObj = jsValue->ToObject(); v8::Local<v8::Object> jsObj = jsValue->ToObject();
@ -202,7 +203,7 @@ int php_v8js_v8_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *re
MAKE_STD_ZVAL(value); MAKE_STD_ZVAL(value);
if (v8js_to_zval(jsVal, value, flags TSRMLS_CC) == FAILURE) { if (v8js_to_zval(jsVal, value, flags, isolate TSRMLS_CC) == FAILURE) {
zval_ptr_dtor(&value); zval_ptr_dtor(&value);
return FAILURE; return FAILURE;
} }
@ -223,19 +224,17 @@ static HashTable *php_v8js_v8_get_properties(zval *object TSRMLS_DC) /* {{{ */
{ {
php_v8js_object *obj = (php_v8js_object *) zend_object_store_get_object(object TSRMLS_CC); php_v8js_object *obj = (php_v8js_object *) zend_object_store_get_object(object TSRMLS_CC);
HashTable *retval; HashTable *retval;
ALLOC_HASHTABLE(retval); ALLOC_HASHTABLE(retval);
zend_hash_init(retval, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(retval, 0, NULL, ZVAL_PTR_DTOR, 0);
php_v8js_ctx *c = (php_v8js_ctx *)v8::Context::GetCurrent()->GetAlignedPointerFromEmbedderData(1); v8::Locker locker(obj->isolate);
v8::Locker locker(c->isolate); v8::Isolate::Scope isolate_scope(obj->isolate);
v8::Isolate::Scope isolate_scope(c->isolate); v8::HandleScope local_scope(obj->isolate);
v8::HandleScope local_scope(c->isolate);
v8::Handle<v8::Context> temp_context = v8::Context::New(); v8::Handle<v8::Context> temp_context = v8::Context::New();
v8::Context::Scope temp_scope(temp_context); v8::Context::Scope temp_scope(temp_context);
if (php_v8js_v8_get_properties_hash(obj->v8obj, retval, obj->flags TSRMLS_CC) == SUCCESS) { if (php_v8js_v8_get_properties_hash(obj->v8obj, retval, obj->flags, obj->isolate TSRMLS_CC) == SUCCESS) {
return retval; return retval;
} }
return NULL; return NULL;
@ -306,7 +305,7 @@ static int php_v8js_v8_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) /
v8::Local<v8::Value> js_retval; v8::Local<v8::Value> js_retval;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
jsArgv[i] = v8::Local<v8::Value>::New(zval_to_v8js(*argv[i] TSRMLS_CC)); jsArgv[i] = v8::Local<v8::Value>::New(zval_to_v8js(*argv[i], obj->isolate TSRMLS_CC));
} }
js_retval = cb->Call(V8JS_GLOBAL, argc, jsArgv); js_retval = cb->Call(V8JS_GLOBAL, argc, jsArgv);
@ -318,7 +317,7 @@ static int php_v8js_v8_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) /
} }
if (return_value_used) { if (return_value_used) {
return v8js_to_zval(js_retval, return_value, obj->flags TSRMLS_CC); return v8js_to_zval(js_retval, return_value, obj->flags, obj->isolate TSRMLS_CC);
} }
return SUCCESS; return SUCCESS;
@ -381,7 +380,7 @@ static zend_object_value php_v8js_v8_new(zend_class_entry *ce TSRMLS_DC) /* {{{
} }
/* }}} */ /* }}} */
void php_v8js_create_v8(zval *res, v8::Handle<v8::Value> value, int flags TSRMLS_DC) /* {{{ */ void php_v8js_create_v8(zval *res, v8::Handle<v8::Value> value, int flags, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
php_v8js_object *c; php_v8js_object *c;
@ -391,6 +390,7 @@ void php_v8js_create_v8(zval *res, v8::Handle<v8::Value> value, int flags TSRMLS
c->v8obj = v8::Persistent<v8::Value>::New(value); c->v8obj = v8::Persistent<v8::Value>::New(value);
c->flags = flags; c->flags = flags;
c->isolate = isolate;
} }
/* }}} */ /* }}} */
@ -626,7 +626,7 @@ static PHP_METHOD(V8Js, __construct)
/* Register Get accessor for passed variables */ /* Register Get accessor for passed variables */
if (vars_arr && zend_hash_num_elements(Z_ARRVAL_P(vars_arr)) > 0) { if (vars_arr && zend_hash_num_elements(Z_ARRVAL_P(vars_arr)) > 0) {
php_v8js_register_accessors(php_obj_t->InstanceTemplate(), vars_arr TSRMLS_CC); php_v8js_register_accessors(php_obj_t->InstanceTemplate(), vars_arr, c->isolate TSRMLS_CC);
} }
/* Set name for the PHP JS object */ /* Set name for the PHP JS object */
@ -847,7 +847,7 @@ static PHP_METHOD(V8Js, executeString)
/* Convert V8 value to PHP value */ /* Convert V8 value to PHP value */
if (!result.IsEmpty()) { if (!result.IsEmpty()) {
v8js_to_zval(result, return_value, flags TSRMLS_CC); v8js_to_zval(result, return_value, flags, c->isolate TSRMLS_CC);
} }
} }
/* }}} */ /* }}} */
@ -1090,7 +1090,7 @@ static void php_v8js_write_property(zval *object, zval *member, zval *value ZEND
v8::Local<v8::Object> jsobj = V8JS_GLOBAL->Get(c->object_name)->ToObject(); v8::Local<v8::Object> jsobj = V8JS_GLOBAL->Get(c->object_name)->ToObject();
/* Write value to PHP JS object */ /* Write value to PHP JS object */
jsobj->ForceSet(V8JS_SYML(Z_STRVAL_P(member), Z_STRLEN_P(member)), zval_to_v8js(value TSRMLS_CC), v8::ReadOnly); jsobj->ForceSet(V8JS_SYML(Z_STRVAL_P(member), Z_STRLEN_P(member)), zval_to_v8js(value, c->isolate TSRMLS_CC), v8::ReadOnly);
/* Write value to PHP object */ /* Write value to PHP object */
std_object_handlers.write_property(object, member, value ZEND_HASH_KEY_CC TSRMLS_CC); std_object_handlers.write_property(object, member, value ZEND_HASH_KEY_CC TSRMLS_CC);

View File

@ -38,6 +38,7 @@ static v8::Handle<v8::Value> php_v8js_php_callback(const v8::Arguments &args) /*
{ {
v8::Handle<v8::Value> return_value; v8::Handle<v8::Value> return_value;
zval *value = reinterpret_cast<zval *>(args.This()->GetAlignedPointerFromInternalField(0)); zval *value = reinterpret_cast<zval *>(args.This()->GetAlignedPointerFromInternalField(0));
v8::Isolate *isolate = reinterpret_cast<v8::Isolate *>(args.This()->GetAlignedPointerFromInternalField(1));
zend_function *method_ptr; zend_function *method_ptr;
zend_fcall_info fci; zend_fcall_info fci;
zend_fcall_info_cache fcc; zend_fcall_info_cache fcc;
@ -99,7 +100,7 @@ static v8::Handle<v8::Value> php_v8js_php_callback(const v8::Arguments &args) /*
argv = (zval **) safe_emalloc(argc, sizeof(zval *), 0); argv = (zval **) safe_emalloc(argc, sizeof(zval *), 0);
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
MAKE_STD_ZVAL(argv[i]); MAKE_STD_ZVAL(argv[i]);
if (v8js_to_zval(args[i], argv[i], flags TSRMLS_CC) == FAILURE) { if (v8js_to_zval(args[i], argv[i], flags, isolate TSRMLS_CC) == FAILURE) {
fci.param_count++; fci.param_count++;
error_len = spprintf(&error, 0, "converting parameter #%d passed to %s() failed", i + 1, method_ptr->common.function_name); error_len = spprintf(&error, 0, "converting parameter #%d passed to %s() failed", i + 1, method_ptr->common.function_name);
return_value = V8JS_THROW(Error, error, error_len); return_value = V8JS_THROW(Error, error, error_len);
@ -134,7 +135,7 @@ failure:
} }
if (retval_ptr != NULL) { if (retval_ptr != NULL) {
return_value = zval_to_v8js(retval_ptr TSRMLS_CC); return_value = zval_to_v8js(retval_ptr, isolate TSRMLS_CC);
zval_ptr_dtor(&retval_ptr); zval_ptr_dtor(&retval_ptr);
} else { } else {
return_value = V8JS_NULL; return_value = V8JS_NULL;
@ -275,7 +276,7 @@ static v8::Handle<v8::Integer> php_v8js_property_query(v8::Local<v8::String> pro
#define PHP_V8JS_CALLBACK(mptr) \ #define PHP_V8JS_CALLBACK(mptr) \
v8::FunctionTemplate::New(php_v8js_php_callback, v8::External::New(mptr))->GetFunction() v8::FunctionTemplate::New(php_v8js_php_callback, v8::External::New(mptr))->GetFunction()
static v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value TSRMLS_DC) /* {{{ */ static v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
v8::Local<v8::FunctionTemplate> new_tpl = v8::FunctionTemplate::New(); v8::Local<v8::FunctionTemplate> new_tpl = v8::FunctionTemplate::New();
v8::Local<v8::Object> newobj; v8::Local<v8::Object> newobj;
@ -303,7 +304,7 @@ static v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value TSRMLS_DC) /* {{
/* Object methods */ /* Object methods */
if (ce) { if (ce) {
new_tpl->SetClassName(V8JS_STRL(ce->name, ce->name_length)); 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) { if (ce == zend_ce_closure) {
new_tpl->InstanceTemplate()->SetCallAsFunctionHandler(php_v8js_php_callback); new_tpl->InstanceTemplate()->SetCallAsFunctionHandler(php_v8js_php_callback);
@ -390,6 +391,7 @@ static v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value TSRMLS_DC) /* {{
Z_ADDREF_P(value); Z_ADDREF_P(value);
newobj->SetAlignedPointerInInternalField(0, (void *) value); newobj->SetAlignedPointerInInternalField(0, (void *) value);
newobj->SetAlignedPointerInInternalField(1, (void *) isolate);
} else { } else {
new_tpl->SetClassName(V8JS_SYM("Array")); new_tpl->SetClassName(V8JS_SYM("Array"));
newobj = new_tpl->InstanceTemplate()->NewInstance(); newobj = new_tpl->InstanceTemplate()->NewInstance();
@ -426,9 +428,9 @@ static v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value TSRMLS_DC) /* {{
} }
continue; continue;
} }
newobj->Set(V8JS_STRL(key, key_len - 1), zval_to_v8js(*data TSRMLS_CC), v8::ReadOnly); newobj->Set(V8JS_STRL(key, key_len - 1), zval_to_v8js(*data, isolate TSRMLS_CC), v8::ReadOnly);
} else { } else {
newobj->Set(index, zval_to_v8js(*data TSRMLS_CC)); newobj->Set(index, zval_to_v8js(*data, isolate TSRMLS_CC));
} }
if (tmp_ht) { if (tmp_ht) {
@ -441,14 +443,14 @@ static v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value TSRMLS_DC) /* {{
} }
/* }}} */ /* }}} */
static v8::Handle<v8::Value> php_v8js_hash_to_jsarr(zval *value TSRMLS_DC) /* {{{ */ static v8::Handle<v8::Value> php_v8js_hash_to_jsarr(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
HashTable *myht = HASH_OF(value); HashTable *myht = HASH_OF(value);
int i = myht ? zend_hash_num_elements(myht) : 0; int i = myht ? zend_hash_num_elements(myht) : 0;
/* Return object if dealing with assoc array */ /* Return object if dealing with assoc array */
if (i > 0 && _php_v8js_is_assoc_array(myht TSRMLS_CC)) { if (i > 0 && _php_v8js_is_assoc_array(myht TSRMLS_CC)) {
return php_v8js_hash_to_jsobj(value TSRMLS_CC); return php_v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
} }
v8::Local<v8::Array> newarr; v8::Local<v8::Array> newarr;
@ -477,7 +479,7 @@ static v8::Handle<v8::Value> php_v8js_hash_to_jsarr(zval *value TSRMLS_DC) /* {{
tmp_ht->nApplyCount++; tmp_ht->nApplyCount++;
} }
newarr->Set(index++, zval_to_v8js(*data TSRMLS_CC)); newarr->Set(index++, zval_to_v8js(*data, isolate TSRMLS_CC));
if (tmp_ht) { if (tmp_ht) {
tmp_ht->nApplyCount--; tmp_ht->nApplyCount--;
@ -488,18 +490,18 @@ static v8::Handle<v8::Value> php_v8js_hash_to_jsarr(zval *value TSRMLS_DC) /* {{
} }
/* }}} */ /* }}} */
v8::Handle<v8::Value> zval_to_v8js(zval *value TSRMLS_DC) /* {{{ */ v8::Handle<v8::Value> zval_to_v8js(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
v8::Handle<v8::Value> jsValue; v8::Handle<v8::Value> jsValue;
switch (Z_TYPE_P(value)) switch (Z_TYPE_P(value))
{ {
case IS_ARRAY: case IS_ARRAY:
jsValue = php_v8js_hash_to_jsarr(value TSRMLS_CC); jsValue = php_v8js_hash_to_jsarr(value, isolate TSRMLS_CC);
break; break;
case IS_OBJECT: case IS_OBJECT:
jsValue = php_v8js_hash_to_jsobj(value TSRMLS_CC); jsValue = php_v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
break; break;
case IS_STRING: case IS_STRING:
@ -527,7 +529,7 @@ v8::Handle<v8::Value> zval_to_v8js(zval *value TSRMLS_DC) /* {{{ */
} }
/* }}} */ /* }}} */
int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags TSRMLS_DC) /* {{{ */ int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
if (jsValue->IsString()) if (jsValue->IsString())
{ {
@ -576,9 +578,9 @@ int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags TS
{ {
if ((flags & V8JS_FLAG_FORCE_ARRAY) || jsValue->IsArray()) { if ((flags & V8JS_FLAG_FORCE_ARRAY) || jsValue->IsArray()) {
array_init(return_value); array_init(return_value);
return php_v8js_v8_get_properties_hash(jsValue, Z_ARRVAL_P(return_value), flags TSRMLS_CC); return php_v8js_v8_get_properties_hash(jsValue, Z_ARRVAL_P(return_value), flags, isolate TSRMLS_CC);
} else { } else {
php_v8js_create_v8(return_value, jsValue, flags TSRMLS_CC); php_v8js_create_v8(return_value, jsValue, flags, isolate TSRMLS_CC);
return SUCCESS; return SUCCESS;
} }
} }

View File

@ -29,26 +29,34 @@ extern "C" {
#include "php_v8js_macros.h" #include "php_v8js_macros.h"
#include <v8.h> #include <v8.h>
#include <string>
struct php_v8js_accessor_ctx
{
char *variable_name_string;
uint variable_name_string_len;
v8::Isolate *isolate;
};
static v8::Handle<v8::Value> php_v8js_fetch_php_variable(v8::Local<v8::String> name, const v8::AccessorInfo &info) /* {{{ */ static v8::Handle<v8::Value> php_v8js_fetch_php_variable(v8::Local<v8::String> name, const v8::AccessorInfo &info) /* {{{ */
{ {
v8::String::Utf8Value variable_name(info.Data()->ToString()); v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(info.Data());
const char *variable_name_string = ToCString(variable_name); php_v8js_accessor_ctx *ctx = static_cast<php_v8js_accessor_ctx *>(data->Value());
uint variable_name_string_len = strlen(variable_name_string);
zval **variable; zval **variable;
TSRMLS_FETCH(); TSRMLS_FETCH();
zend_is_auto_global(variable_name_string, variable_name_string_len TSRMLS_CC); zend_is_auto_global(ctx->variable_name_string, ctx->variable_name_string_len TSRMLS_CC);
if (zend_hash_find(&EG(symbol_table), variable_name_string, variable_name_string_len + 1, (void **) &variable) == SUCCESS) { if (zend_hash_find(&EG(symbol_table), ctx->variable_name_string, ctx->variable_name_string_len + 1, (void **) &variable) == SUCCESS) {
return zval_to_v8js(*variable TSRMLS_CC); return zval_to_v8js(*variable, ctx->isolate TSRMLS_CC);
} }
return v8::Undefined(); return v8::Undefined();
} }
/* }}} */ /* }}} */
void php_v8js_register_accessors(v8::Local<v8::ObjectTemplate> php_obj, zval *array TSRMLS_DC) /* {{{ */ void php_v8js_register_accessors(v8::Local<v8::ObjectTemplate> php_obj, zval *array, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{ {
char *property_name; char *property_name;
uint property_name_len; uint property_name_len;
@ -76,8 +84,14 @@ void php_v8js_register_accessors(v8::Local<v8::ObjectTemplate> php_obj, zval *ar
continue; /* Ignore invalid property names */ continue; /* Ignore invalid property names */
} }
// Create context to store accessor data
php_v8js_accessor_ctx *ctx = (php_v8js_accessor_ctx *)emalloc(sizeof(php_v8js_accessor_ctx));
ctx->variable_name_string = estrdup(Z_STRVAL_PP(item));
ctx->variable_name_string_len = Z_STRLEN_PP(item);
ctx->isolate = isolate;
/* Set the variable fetch callback for given symbol on named property */ /* Set the variable fetch callback for given symbol on named property */
php_obj->SetAccessor(V8JS_STRL(property_name, property_name_len - 1), php_v8js_fetch_php_variable, NULL, V8JS_STRL(Z_STRVAL_PP(item), Z_STRLEN_PP(item)), v8::PROHIBITS_OVERWRITING, v8::ReadOnly); php_obj->SetAccessor(V8JS_STRL(property_name, property_name_len - 1), php_v8js_fetch_php_variable, NULL, v8::External::New(ctx), v8::PROHIBITS_OVERWRITING, v8::ReadOnly);
} }
} }
/* }}} */ /* }}} */