diff --git a/tests/return_this_001.phpt b/tests/return_this_001.phpt new file mode 100644 index 0000000..93ff987 --- /dev/null +++ b/tests/return_this_001.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test V8::executeString() : return this (aka fluent setters, JS-side) +--SKIPIF-- + +--FILE-- +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=== diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index 20f01dc..8f5a126 100644 --- a/v8js_v8object_class.cc +++ b/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::Isolate *) > v8_call = [obj, method, argc, argv TSRMLS_CC](v8::Isolate *isolate) { + std::function< v8::Local(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value TSRMLS_CC](v8::Isolate *isolate) { int i = 0; v8::Local method_name = V8JS_SYML(method, strlen(method)); @@ -328,7 +328,15 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) jsArgv[i] = v8::Local::New(isolate, zval_to_v8js(*argv[i], isolate TSRMLS_CC)); } - return cb->Call(thisObj, argc, jsArgv); + v8::Local result = cb->Call(thisObj, argc, jsArgv); + + if (obj->std.ce == php_ce_v8object && result->StrictEquals(thisObj)) { + /* JS code did "return this", retain object identity */ + RETVAL_ZVAL(object, 1, 0); + 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);