Skip to content

Commit 61febfb

Browse files
committed
Merge pull request #186 from stesie/issue-185
Provide correct "this" on V8Object method invocation, closes #185
2 parents 30fe993 + 3c5508b commit 61febfb

File tree

4 files changed

+107
-1
lines changed

4 files changed

+107
-1
lines changed

tests/issue_185_001.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Test V8::executeString() : Issue #185 this on direct invocation of method
3+
--SKIPIF--
4+
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
$v8 = new V8Js();
9+
10+
$JS = <<<EOT
11+
12+
function Bar(i) {
13+
this.theValue = i;
14+
}
15+
Bar.prototype.tell = function() {
16+
var_dump(this.theValue);
17+
var_dump(typeof this.exit);
18+
};
19+
var inst = new Bar(23);
20+
var fn = inst.tell;
21+
fn();
22+
EOT;
23+
24+
$v8->executeString($JS);
25+
26+
// now fetch `inst` from V8 and call method from PHP
27+
$fn = $v8->executeString('(inst.tell)');
28+
$fn();
29+
?>
30+
===EOF===
31+
--EXPECT--
32+
NULL
33+
string(8) "function"
34+
NULL
35+
string(8) "function"
36+
===EOF===

tests/issue_185_002.phpt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Test V8::executeString() : Issue #185 this on function invocation
3+
--SKIPIF--
4+
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
$v8 = new V8Js();
9+
10+
$JS = <<<EOT
11+
12+
function fn() {
13+
var_dump(typeof this.exit);
14+
};
15+
fn();
16+
EOT;
17+
18+
$v8->executeString($JS);
19+
20+
// now fetch `inst` from V8 and call method from PHP
21+
$fn = $v8->executeString('(fn)');
22+
$fn();
23+
?>
24+
===EOF===
25+
--EXPECT--
26+
string(8) "function"
27+
string(8) "function"
28+
===EOF===

tests/issue_185_basic.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Test V8::executeString() : Issue #185 Wrong this on V8Object method invocation
3+
--SKIPIF--
4+
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
$v8 = new V8Js();
9+
10+
$JS = <<<EOT
11+
12+
function Bar(i) {
13+
this.theValue = i;
14+
}
15+
Bar.prototype.tell = function() {
16+
var_dump(this.theValue);
17+
};
18+
var inst = new Bar(23);
19+
inst.tell();
20+
EOT;
21+
22+
$v8->executeString($JS);
23+
24+
// now fetch `inst` from V8 and call method from PHP
25+
$inst = $v8->executeString('(inst)');
26+
$inst->tell();
27+
?>
28+
===EOF===
29+
--EXPECT--
30+
int(23)
31+
int(23)
32+
===EOF===

v8js_v8object_class.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
302302

303303
v8::Local<v8::String> method_name = V8JS_SYML(method, strlen(method));
304304
v8::Local<v8::Object> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj)->ToObject();
305+
v8::Local<v8::Object> thisObj;
305306
v8::Local<v8::Function> cb;
306307

307308
if (method_name->Equals(V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME))) {
@@ -310,6 +311,15 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
310311
cb = v8::Local<v8::Function>::Cast(v8obj->Get(method_name));
311312
}
312313

314+
// If a method is invoked on V8Object, then set the object itself as
315+
// "this" on JS side. Otherwise fall back to global object.
316+
if (obj->std.ce == php_ce_v8object) {
317+
thisObj = v8obj;
318+
}
319+
else {
320+
thisObj = V8JS_GLOBAL(isolate);
321+
}
322+
313323
v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc));
314324
v8::Local<v8::Value> js_retval;
315325

@@ -318,7 +328,7 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
318328
jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(*argv[i], isolate TSRMLS_CC));
319329
}
320330

321-
return cb->Call(V8JS_GLOBAL(isolate), argc, jsArgv);
331+
return cb->Call(thisObj, argc, jsArgv);
322332
};
323333

324334
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)