0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-09 15:18:41 +00:00

Provide correct "this" on V8Object method invocation, closes #185

This commit is contained in:
Stefan Siegl 2015-12-26 12:16:17 +01:00
parent d9e4ae5abe
commit 3c5508b956
4 changed files with 107 additions and 1 deletions

36
tests/issue_185_001.phpt Normal file
View File

@ -0,0 +1,36 @@
--TEST--
Test V8::executeString() : Issue #185 this on direct invocation of method
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
$v8 = new V8Js();
$JS = <<<EOT
function Bar(i) {
this.theValue = i;
}
Bar.prototype.tell = function() {
var_dump(this.theValue);
var_dump(typeof this.exit);
};
var inst = new Bar(23);
var fn = inst.tell;
fn();
EOT;
$v8->executeString($JS);
// now fetch `inst` from V8 and call method from PHP
$fn = $v8->executeString('(inst.tell)');
$fn();
?>
===EOF===
--EXPECT--
NULL
string(8) "function"
NULL
string(8) "function"
===EOF===

28
tests/issue_185_002.phpt Normal file
View File

@ -0,0 +1,28 @@
--TEST--
Test V8::executeString() : Issue #185 this on function invocation
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
$v8 = new V8Js();
$JS = <<<EOT
function fn() {
var_dump(typeof this.exit);
};
fn();
EOT;
$v8->executeString($JS);
// now fetch `inst` from V8 and call method from PHP
$fn = $v8->executeString('(fn)');
$fn();
?>
===EOF===
--EXPECT--
string(8) "function"
string(8) "function"
===EOF===

View File

@ -0,0 +1,32 @@
--TEST--
Test V8::executeString() : Issue #185 Wrong this on V8Object method invocation
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
$v8 = new V8Js();
$JS = <<<EOT
function Bar(i) {
this.theValue = i;
}
Bar.prototype.tell = function() {
var_dump(this.theValue);
};
var inst = new Bar(23);
inst.tell();
EOT;
$v8->executeString($JS);
// now fetch `inst` from V8 and call method from PHP
$inst = $v8->executeString('(inst)');
$inst->tell();
?>
===EOF===
--EXPECT--
int(23)
int(23)
===EOF===

View File

@ -302,6 +302,7 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
v8::Local<v8::String> method_name = V8JS_SYML(method, strlen(method)); v8::Local<v8::String> method_name = V8JS_SYML(method, strlen(method));
v8::Local<v8::Object> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj)->ToObject(); v8::Local<v8::Object> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj)->ToObject();
v8::Local<v8::Object> thisObj;
v8::Local<v8::Function> cb; v8::Local<v8::Function> cb;
if (method_name->Equals(V8JS_SYM(V8JS_V8_INVOKE_FUNC_NAME))) { 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)
cb = v8::Local<v8::Function>::Cast(v8obj->Get(method_name)); cb = v8::Local<v8::Function>::Cast(v8obj->Get(method_name));
} }
// If a method is invoked on V8Object, then set the object itself as
// "this" on JS side. Otherwise fall back to global object.
if (obj->std.ce == php_ce_v8object) {
thisObj = v8obj;
}
else {
thisObj = V8JS_GLOBAL(isolate);
}
v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc)); v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc));
v8::Local<v8::Value> js_retval; v8::Local<v8::Value> js_retval;
@ -318,7 +328,7 @@ 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)); jsArgv[i] = v8::Local<v8::Value>::New(isolate, zval_to_v8js(*argv[i], isolate TSRMLS_CC));
} }
return cb->Call(V8JS_GLOBAL(isolate), argc, jsArgv); return cb->Call(thisObj, argc, jsArgv);
}; };
v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call TSRMLS_CC); v8js_v8_call(obj->ctx, &return_value, obj->flags, obj->ctx->time_limit, obj->ctx->memory_limit, v8_call TSRMLS_CC);