Skip to content

Commit b0f761a

Browse files
committed
Merge pull request #221 from stesie/fluent-setters-js
Retain object identity on JS-side 'return this'
2 parents 07c81e5 + 5595c3b commit b0f761a

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

tests/return_this_001.phpt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
Test V8::executeString() : return this (aka fluent setters, JS-side)
3+
--SKIPIF--
4+
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
$js = <<<EOJS
9+
function Bar() {
10+
}
11+
12+
Bar.prototype.setFoo = function(value) {
13+
this.foo = value;
14+
return this;
15+
}
16+
17+
Bar.prototype.setBar = function(value) {
18+
this.bar = value;
19+
return this;
20+
}
21+
22+
theBar = new Bar();
23+
(theBar);
24+
EOJS;
25+
26+
$v8 = new V8Js();
27+
$bar = $v8->executeString($js);
28+
29+
$ret = $bar->setFoo(23)->setBar(42);
30+
var_dump($bar === $ret);
31+
32+
$v8->executeString('var_dump(theBar);');
33+
34+
?>
35+
===EOF===
36+
--EXPECTF--
37+
bool(true)
38+
object(Bar)#%d (2) {
39+
["foo"] =>
40+
int(23)
41+
["bar"] =>
42+
int(42)
43+
}
44+
===EOF===

v8js_v8object_class.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
297297
zend_get_parameters_array_ex(argc, argv);
298298
}
299299

300-
std::function< v8::Local<v8::Value>(v8::Isolate *) > v8_call = [obj, method, argc, argv TSRMLS_CC](v8::Isolate *isolate) {
300+
std::function< v8::Local<v8::Value>(v8::Isolate *) > v8_call = [obj, method, argc, argv, object, &return_value TSRMLS_CC](v8::Isolate *isolate) {
301301
int i = 0;
302302

303303
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)
328328
jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(*argv[i], isolate TSRMLS_CC));
329329
}
330330

331-
return cb->Call(thisObj, argc, jsArgv);
331+
v8::Local<v8::Value> result = cb->Call(thisObj, argc, jsArgv);
332+
333+
if (obj->std.ce == php_ce_v8object && result->StrictEquals(thisObj)) {
334+
/* JS code did "return this", retain object identity */
335+
ZVAL_COPY_VALUE(return_value, object);
336+
zval_copy_ctor(return_value);
337+
result.Clear();
338+
}
339+
340+
return result;
332341
};
333342

334343
v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call TSRMLS_CC);

0 commit comments

Comments
 (0)