[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pecl-cvs
Subject:    [PECL-CVS] com pecl/languages/v8js: Export extra methods on ArrayAccess: =?UTF-8?Q?tests/array=5Facc
From:       Stefan Siegl <stesie () php ! net>
Date:       2014-11-29 19:35:32
Message-ID: php-mail-265856507ed079ef5fb3fdcc9fae8a241708909603 () git ! php ! net
[Download RAW message or body]

Commit:    2b897e8bc4d85138ed8c98c54de0f9a4533b8868
Author:    Stefan Siegl <stesie@brokenpipe.de>         Sat, 29 Nov 2014 20:35:32 \
                +0100
Parents:   02d8ecc16e92b4bb608498666aef35f1d663fe06
Branches:  master

Link:       http://git.php.net/?p=pecl/languages/v8js.git;a=commitdiff;h=2b897e8bc4d85138ed8c98c54de0f9a4533b8868


Log:
Export extra methods on ArrayAccess

This merges the distinct code path for the export of ArrayAccess
capable PHP objects back into the "common" PHP object export code.
Sole difference is that the ArrayAccess-style object has index
property handlers as well as property bridging to Array.prototype.

Changed paths:
  A  tests/array_access_003.phpt
  M  v8js_array_access.cc
  M  v8js_array_access.h
  M  v8js_object_export.cc
  M  v8js_object_export.h


["diff_2b897e8bc4d85138ed8c98c54de0f9a4533b8868.txt" (text/plain)]

diff --git a/tests/array_access_003.phpt b/tests/array_access_003.phpt
new file mode 100644
index 0000000..c7a5f1b
--- /dev/null
+++ b/tests/array_access_003.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Test V8::executeString() : Export PHP methods on ArrayAccess objects
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+v8js.use_array_access = 1
+--FILE--
+<?php
+
+class MyArray implements ArrayAccess, Countable {
+    private $data = Array('one', 'two', 'three');
+
+    public function offsetExists($offset) {
+	return isset($this->data[$offset]);
+    }
+
+    public function offsetGet($offset) {
+	return $this->data[$offset];
+    }
+
+    public function offsetSet($offset, $value) {
+	echo "set[$offset] = $value\n";
+	$this->data[$offset] = $value;
+    }
+
+    public function offsetUnset($offset) {
+        throw new Exception('Not implemented');
+    }
+
+    public function count() {
+	echo 'count() = ', count($this->data), "\n";
+        return count($this->data);
+    }
+
+    public function phpSidePush($value) {
+	echo "push << $value\n";
+	$this->data[] = $value;
+    }
+}
+
+$v8 = new V8Js();
+$v8->myarr = new MyArray();
+
+/* Call PHP method to modify the array. */
+$v8->executeString('PHP.myarr.phpSidePush(23);');
+
+var_dump(count($v8->myarr));
+var_dump($v8->myarr[3]);
+
+/* And JS should see the changes due to live binding. */
+$v8->executeString('var_dump(PHP.myarr.join(","));');
+
+?>
+===EOF===
+--EXPECT--
+push << 23
+count() = 4
+int(4)
+int(23)
+count() = 4
+string(16) "one,two,three,23"
+===EOF===
diff --git a/v8js_array_access.cc b/v8js_array_access.cc
index b54626d..8fad0d8 100644
--- a/v8js_array_access.cc
+++ b/v8js_array_access.cc
@@ -24,8 +24,9 @@ extern "C" {
 
 #include "php_v8js_macros.h"
 #include "v8js_array_access.h"
+#include "v8js_object_export.h"
 
-static void php_v8js_array_access_getter(uint32_t index, const \
v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */ +void \
php_v8js_array_access_getter(uint32_t index, const \
v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */  {
 	v8::Isolate *isolate = info.GetIsolate();
 	v8::Local<v8::Object> self = info.Holder();
@@ -71,8 +72,8 @@ static void php_v8js_array_access_getter(uint32_t index, const \
v8::PropertyCallb  }
 /* }}} */
 
-static void php_v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
-										 const v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */
+void php_v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
+								  const v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */
 {
 	v8::Isolate *isolate = info.GetIsolate();
 	v8::Local<v8::Object> self = info.Holder();
@@ -130,7 +131,7 @@ static void php_v8js_array_access_setter(uint32_t index, \
v8::Local<v8::Value> va  }
 /* }}} */
 
-static void php_v8js_array_access_length(v8::Local<v8::String> property, const \
v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */ +void \
php_v8js_array_access_length(v8::Local<v8::String> property, const \
v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */  {
 	v8::Isolate *isolate = info.GetIsolate();
 	v8::Local<v8::Object> self = info.Holder();
@@ -169,26 +170,35 @@ static void php_v8js_array_access_length(v8::Local<v8::String> \
property, const v  }
 /* }}} */
 
-
-v8::Handle<v8::Value> php_v8js_array_access_to_jsobj(zval *value, v8::Isolate \
*isolate TSRMLS_DC) /* {{{ */ +void \
php_v8js_array_access_named_getter(v8::Local<v8::String> property, const \
v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */  {
-	v8::Local<v8::ObjectTemplate> inst_tpl = v8::ObjectTemplate::New(isolate);
-	inst_tpl->SetIndexedPropertyHandler(php_v8js_array_access_getter,
-										php_v8js_array_access_setter);
-	inst_tpl->SetAccessor(V8JS_STR("length"), php_v8js_array_access_length);
+	v8::String::Utf8Value cstr(property);
+	const char *name = ToCString(cstr);
+
+	if(strcmp(name, "length") == 0) {
+		php_v8js_array_access_length(property, info);
+		return;
+	}
+
+	v8::Local<v8::Value> ret_value = php_v8js_named_property_callback(property, info, \
V8JS_PROP_GETTER);  
-	v8::Handle<v8::Object> newobj = inst_tpl->NewInstance();
-	newobj->SetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY), v8::External::New(isolate, \
value)); +	if(ret_value.IsEmpty()) {
+		v8::Isolate *isolate = info.GetIsolate();
+		v8::Local<v8::Array> arr = v8::Array::New(isolate);
+		v8::Local<v8::Value> prototype = arr->GetPrototype();
 
-	/* Change prototype of `newobj' to that of Array */
-	v8::Local<v8::Array> arr = v8::Array::New(isolate);
-	newobj->SetPrototype(arr->GetPrototype());
+		if(!prototype->IsObject()) {
+			/* ehh?  Array.prototype not an object? strange, stop. */
+			info.GetReturnValue().Set(ret_value);
+		}
 
-	return newobj;
+		ret_value = prototype->ToObject()->Get(property);
+	}
+
+	info.GetReturnValue().Set(ret_value);
 }
 /* }}} */
 
-
 /*
  * Local variables:
  * tab-width: 4
diff --git a/v8js_array_access.h b/v8js_array_access.h
index 12ace26..af4a0f9 100644
--- a/v8js_array_access.h
+++ b/v8js_array_access.h
@@ -13,6 +13,16 @@
 #ifndef V8JS_ARRAY_ACCESS_H
 #define V8JS_ARRAY_ACCESS_H
 
-v8::Handle<v8::Value> php_v8js_array_access_to_jsobj(zval *value, v8::Isolate \
*isolate TSRMLS_DC); +/* Indexed Property Handlers */
+void php_v8js_array_access_getter(uint32_t index,
+				  const v8::PropertyCallbackInfo<v8::Value>& info);
+void php_v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
+				  const v8::PropertyCallbackInfo<v8::Value>& info);
+void php_v8js_array_access_length(v8::Local<v8::String> property,
+				  const v8::PropertyCallbackInfo<v8::Value>& info);
+
+/* Named Property Handlers */
+void php_v8js_array_access_named_getter(v8::Local<v8::String> property,
+					const v8::PropertyCallbackInfo<v8::Value> &info);
 
 #endif /* V8JS_ARRAY_ACCESS_H */
diff --git a/v8js_object_export.cc b/v8js_object_export.cc
index dd55df9..f141e40 100644
--- a/v8js_object_export.cc
+++ b/v8js_object_export.cc
@@ -582,16 +582,9 @@ static void php_v8js_fake_call_impl(const \
v8::FunctionCallbackInfo<v8::Value>& i  }
 /* }}} */
 
-typedef enum {
-	V8JS_PROP_GETTER,
-	V8JS_PROP_SETTER,
-	V8JS_PROP_QUERY,
-	V8JS_PROP_DELETER
-} property_op_t;
-
 /* This method handles named property and method get/set/query/delete. */
 template<typename T>
-static inline v8::Local<v8::Value> \
php_v8js_named_property_callback(v8::Local<v8::String> property, const \
v8::PropertyCallbackInfo<T> &info, property_op_t callback_type, v8::Local<v8::Value> \
set_value = v8::Local<v8::Value>()) /* {{{ */ +inline v8::Local<v8::Value> \
php_v8js_named_property_callback(v8::Local<v8::String> property, const \
v8::PropertyCallbackInfo<T> &info, property_op_t callback_type, v8::Local<v8::Value> \
set_value = v8::Local<v8::Value>()) /* {{{ */  {
 	v8::Isolate *isolate = info.GetIsolate();
 	v8::String::Utf8Value cstr(property);
@@ -870,9 +863,39 @@ static v8::Handle<v8::Object> php_v8js_wrap_object(v8::Isolate \
*isolate, zend_cl  persist_tpl_ = &ctx->template_cache[ce->name];
 			persist_tpl_->Reset(isolate, new_tpl);
 			/* We'll free persist_tpl_ when template_cache is destroyed */
+
+			v8::Local<v8::ObjectTemplate> inst_tpl = new_tpl->InstanceTemplate();
+			v8::NamedPropertyGetterCallback getter = php_v8js_named_property_getter;
+
+			/* Check for ArrayAccess object */
+			if (V8JSG(use_array_access) && ce) {
+				bool has_array_access = false;
+				bool has_countable = false;
+
+				for (int i = 0; i < ce->num_interfaces; i ++) {
+					if (strcmp (ce->interfaces[i]->name, "ArrayAccess") == 0) {
+						has_array_access = true;
+					}
+					else if (strcmp (ce->interfaces[i]->name, "Countable") == 0) {
+						has_countable = true;
+					}
+				}
+
+				if(has_array_access && has_countable) {
+					inst_tpl->SetIndexedPropertyHandler(php_v8js_array_access_getter,
+														php_v8js_array_access_setter);
+
+					/* Switch to special ArrayAccess getter, which falls back to
+					 * php_v8js_named_property_getter, but possibly bridges the
+					 * call to Array.prototype functions. */
+					getter = php_v8js_array_access_named_getter;
+				}
+			}
+
+
 			// Finish setup of new_tpl
-			new_tpl->InstanceTemplate()->SetNamedPropertyHandler
-				(php_v8js_named_property_getter, /* getter */
+			inst_tpl->SetNamedPropertyHandler
+				(getter, /* getter */
 				 php_v8js_named_property_setter, /* setter */
 				 php_v8js_named_property_query, /* query */
 				 php_v8js_named_property_deleter, /* deleter */
@@ -991,25 +1014,6 @@ v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value, \
v8::Isolate *isolate T  return V8JS_NULL;
 	}
 
-	/* Check for ArrayAccess object */
-	if (V8JSG(use_array_access) && ce) {
-		bool has_array_access = false;
-		bool has_countable = false;
-
-		for (int i = 0; i < ce->num_interfaces; i ++) {
-			if (strcmp (ce->interfaces[i]->name, "ArrayAccess") == 0) {
-				has_array_access = true;
-			}
-			else if (strcmp (ce->interfaces[i]->name, "Countable") == 0) {
-				has_countable = true;
-			}
-		}
-
-		if(has_array_access && has_countable) {
-			return php_v8js_array_access_to_jsobj(value, isolate TSRMLS_CC);
-		}
-	}
-
 	/* Special case, passing back object originating from JS to JS */
 	if (ce == php_ce_v8_function) {
 		php_v8js_object *c = (php_v8js_object *) zend_object_store_get_object(value \
                TSRMLS_CC);
diff --git a/v8js_object_export.h b/v8js_object_export.h
index c9386e5..94b786e 100644
--- a/v8js_object_export.h
+++ b/v8js_object_export.h
@@ -16,4 +16,18 @@
 
 v8::Handle<v8::Value> php_v8js_hash_to_jsobj(zval *value, v8::Isolate *isolate \
TSRMLS_DC);  
+
+typedef enum {
+	V8JS_PROP_GETTER,
+	V8JS_PROP_SETTER,
+	V8JS_PROP_QUERY,
+	V8JS_PROP_DELETER
+} property_op_t;
+
+template<typename T>
+v8::Local<v8::Value> php_v8js_named_property_callback(v8::Local<v8::String> \
property, +						      const v8::PropertyCallbackInfo<T> &info,
+						      property_op_t callback_type,
+						      v8::Local<v8::Value> set_value = v8::Local<v8::Value>());
+
 #endif /* V8JS_OBJECT_EXPORT_H */



-- 
PECL CVS Mailing List 
To unsubscribe, visit: http://www.php.net/unsub.php

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic