浏览代码

Don't re-wrap PHP objects from V8 to V8Object

Stefan Siegl 11 年之前
父节点
当前提交
bd9483080d
共有 4 个文件被更改,包括 113 次插入25 次删除
  1. 10 14
      tests/object_method_call.phpt
  2. 74 0
      tests/object_passback.phpt
  3. 13 4
      v8js.cc
  4. 16 7
      v8js_convert.cc

+ 10 - 14
tests/object_method_call.phpt

@@ -113,15 +113,13 @@ Mon, 08 Sep 1975 09:00:00 +0000
 string(3) "foo"
 array(3) {
   [0]=>
-  object(V8Object)#4 (3) {
-    ["mytest"]=>
-    object(V8Function)#6 (0) {
-    }
-    ["mydatetest"]=>
-    object(V8Function)#7 (0) {
-    }
+  object(Testing)#2 (3) {
     ["foo"]=>
     string(8) "ORIGINAL"
+    ["my_private":"Testing":private]=>
+    string(3) "arf"
+    ["my_protected":protected]=>
+    string(4) "argh"
   }
   [1]=>
   array(3) {
@@ -139,15 +137,13 @@ array(3) {
     [1]=>
     string(3) "bar"
     [2]=>
-    object(V8Object)#5 (3) {
-      ["mytest"]=>
-      object(V8Function)#7 (0) {
-      }
-      ["mydatetest"]=>
-      object(V8Function)#6 (0) {
-      }
+    object(Testing)#2 (3) {
       ["foo"]=>
       string(8) "ORIGINAL"
+      ["my_private":"Testing":private]=>
+      string(3) "arf"
+      ["my_protected":protected]=>
+      string(4) "argh"
     }
   }
 }

+ 74 - 0
tests/object_passback.phpt

@@ -0,0 +1,74 @@
+--TEST--
+Test V8::executeString() : Object passing PHP > JS > PHP
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+
+class Bar {
+  function sayHello() {
+	echo "Hello\n";
+  }
+}
+
+class Foo {
+  function getBar() {
+	return new Bar();
+  }
+
+  function callMulti($list) {
+	foreach($list as $x) {
+	  echo get_class($x)."\n";  // V8Object vs. Bar
+	  $x->sayHello();
+	}
+  }
+
+  function callSingle($inst) {
+	echo get_class($inst)."\n";
+	$inst->sayHello();
+  }
+}
+
+$v8 = new V8Js();
+$v8->foo = new Foo();
+
+$JS = <<< EOF
+var obj = PHP.foo.getBar();
+PHP.foo.callMulti([obj]);
+PHP.foo.callMulti([obj]);
+PHP.foo.callSingle(obj);
+PHP.foo.callSingle(obj);
+
+obj = {};
+obj.sayHello = function() {
+	print("JavaScript Hello\\n");
+};
+
+PHP.foo.callMulti([obj]);
+PHP.foo.callMulti([obj]);
+PHP.foo.callSingle(obj);
+PHP.foo.callSingle(obj);
+EOF;
+
+$v8->executeString($JS);
+
+?>
+===EOF===
+--EXPECT--
+Bar
+Hello
+Bar
+Hello
+Bar
+Hello
+Bar
+Hello
+V8Object
+JavaScript Hello
+V8Object
+JavaScript Hello
+V8Object
+JavaScript Hello
+V8Object
+JavaScript Hello
+===EOF===

+ 13 - 4
v8js.cc

@@ -281,11 +281,20 @@ int php_v8js_v8_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *re
 			const char *key = ToCString(cstr);
 			zval *value = NULL;
 
-			MAKE_STD_ZVAL(value);
+			if(jsVal->IsObject()
+			   && !jsVal->IsFunction()
+			   && jsVal->ToObject()->InternalFieldCount() == 2) {
+				/* This is a PHP object, passed to JS and back. */
+				value = reinterpret_cast<zval *>(jsVal->ToObject()->GetAlignedPointerFromInternalField(0));
+				Z_ADDREF_P(value);
+			}
+			else {
+				MAKE_STD_ZVAL(value);
 
-			if (v8js_to_zval(jsVal, value, flags, isolate TSRMLS_CC) == FAILURE) {
-				zval_ptr_dtor(&value);
-				return FAILURE;
+				if (v8js_to_zval(jsVal, value, flags, isolate TSRMLS_CC) == FAILURE) {
+					zval_ptr_dtor(&value);
+					return FAILURE;
+				}
 			}
 
 			if ((flags & V8JS_FLAG_FORCE_ARRAY) || jsValue->IsArray()) {

+ 16 - 7
v8js_convert.cc

@@ -110,14 +110,23 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct
 		fci.params = (zval ***) safe_emalloc(argc, sizeof(zval **), 0);
 		argv = (zval **) safe_emalloc(argc, sizeof(zval *), 0);
 		for (i = 0; i < argc; i++) {
-			MAKE_STD_ZVAL(argv[i]);
-			if (v8js_to_zval(info[i], argv[i], flags, isolate TSRMLS_CC) == FAILURE) {
-				fci.param_count++;
-				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);
-				efree(error);
-				goto failure;
+			if(info[i]->IsObject()
+			   && !info[i]->IsFunction()
+			   && info[i]->ToObject()->InternalFieldCount() == 2) {
+				/* This is a PHP object, passed to JS and back. */
+				argv[i] = reinterpret_cast<zval *>(info[i]->ToObject()->GetAlignedPointerFromInternalField(0));
+				Z_ADDREF_P(argv[i]);
+			} else {
+				MAKE_STD_ZVAL(argv[i]);
+				if (v8js_to_zval(info[i], argv[i], flags, isolate TSRMLS_CC) == FAILURE) {
+					fci.param_count++;
+					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);
+					efree(error);
+					goto failure;
+				}
 			}
+
 			fci.params[fci.param_count++] = &argv[i];
  		}
 	} else {