Kaynağa Gözat

Merge pull request #221 from stesie/fluent-setters-js

Retain object identity on JS-side 'return this'
Stefan Siegl 9 yıl önce
ebeveyn
işleme
b0f761ae3b
2 değiştirilmiş dosya ile 55 ekleme ve 2 silme
  1. 44 0
      tests/return_this_001.phpt
  2. 11 2
      v8js_v8object_class.cc

+ 44 - 0
tests/return_this_001.phpt

@@ -0,0 +1,44 @@
+--TEST--
+Test V8::executeString() : return this (aka fluent setters, JS-side)
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+
+$js = <<<EOJS
+function Bar() {
+}
+
+Bar.prototype.setFoo = function(value) {
+	this.foo = value;
+	return this;
+}
+
+Bar.prototype.setBar = function(value) {
+	this.bar = value;
+	return this;
+}
+
+theBar = new Bar();
+(theBar);
+EOJS;
+
+$v8 = new V8Js();
+$bar = $v8->executeString($js);
+
+$ret = $bar->setFoo(23)->setBar(42);
+var_dump($bar === $ret);
+
+$v8->executeString('var_dump(theBar);');
+
+?>
+===EOF===
+--EXPECTF--
+bool(true)
+object(Bar)#%d (2) {
+  ["foo"] =>
+  int(23)
+  ["bar"] =>
+  int(42)
+}
+===EOF===

+ 11 - 2
v8js_v8object_class.cc

@@ -297,7 +297,7 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
 		zend_get_parameters_array_ex(argc, argv);
 	}
 
-	std::function< v8::Local<v8::Value>(v8::Isolate *) > v8_call = [obj, method, argc, argv TSRMLS_CC](v8::Isolate *isolate) {
+	std::function< v8::Local<v8::Value>(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value TSRMLS_CC](v8::Isolate *isolate) {
 		int i = 0;
 
 		v8::Local<v8::String> method_name = V8JS_SYML(method, strlen(method));
@@ -328,7 +328,16 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
 			jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(*argv[i], isolate TSRMLS_CC));
 		}
 
-		return cb->Call(thisObj, argc, jsArgv);
+		v8::Local<v8::Value> result = cb->Call(thisObj, argc, jsArgv);
+
+		if (obj->std.ce == php_ce_v8object && result->StrictEquals(thisObj)) {
+			/* JS code did "return this", retain object identity */
+			ZVAL_COPY_VALUE(return_value, object);
+			zval_copy_ctor(return_value);
+			result.Clear();
+		}
+
+		return result;
 	};
 
 	v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call TSRMLS_CC);