From 3c5508b956e0e859f6f6bd933ad716abbe676093 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sat, 26 Dec 2015 12:16:17 +0100 Subject: [PATCH] Provide correct "this" on V8Object method invocation, closes #185 --- tests/issue_185_001.phpt | 36 ++++++++++++++++++++++++++++++++++++ tests/issue_185_002.phpt | 28 ++++++++++++++++++++++++++++ tests/issue_185_basic.phpt | 32 ++++++++++++++++++++++++++++++++ v8js_v8object_class.cc | 12 +++++++++++- 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 tests/issue_185_001.phpt create mode 100644 tests/issue_185_002.phpt create mode 100644 tests/issue_185_basic.phpt diff --git a/tests/issue_185_001.phpt b/tests/issue_185_001.phpt new file mode 100644 index 0000000..166e448 --- /dev/null +++ b/tests/issue_185_001.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test V8::executeString() : Issue #185 this on direct invocation of method +--SKIPIF-- + +--FILE-- +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=== diff --git a/tests/issue_185_002.phpt b/tests/issue_185_002.phpt new file mode 100644 index 0000000..f2aa723 --- /dev/null +++ b/tests/issue_185_002.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test V8::executeString() : Issue #185 this on function invocation +--SKIPIF-- + +--FILE-- +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=== diff --git a/tests/issue_185_basic.phpt b/tests/issue_185_basic.phpt new file mode 100644 index 0000000..9bb562a --- /dev/null +++ b/tests/issue_185_basic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Test V8::executeString() : Issue #185 Wrong this on V8Object method invocation +--SKIPIF-- + +--FILE-- +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=== diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index c51929d..20f01dc 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -302,6 +302,7 @@ static int v8js_v8object_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) v8::Local method_name = V8JS_SYML(method, strlen(method)); v8::Local v8obj = v8::Local::New(isolate, obj->v8obj)->ToObject(); + v8::Local thisObj; v8::Local cb; 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::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 *jsArgv = static_cast *>(alloca(sizeof(v8::Local) * argc)); v8::Local js_retval; @@ -318,7 +328,7 @@ 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(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);