Skip to content
This repository was archived by the owner on Mar 29, 2024. It is now read-only.

Commit 5774a3b

Browse files
committed
Add V8\FunctionTemplate signature support in ctor (simplified to $receiver)
1 parent b586e70 commit 5774a3b

File tree

5 files changed

+93
-9
lines changed

5 files changed

+93
-9
lines changed

src/php_v8_function_template.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,16 @@ static PHP_METHOD(V8FunctionTemplate, __construct) {
131131
zend_fcall_info fci = empty_fcall_info;
132132
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
133133

134+
zval *php_v8_receiver_zv = NULL;
135+
134136
zend_long length = 0;
135137
zend_long behavior = static_cast<zend_long>(v8::ConstructorBehavior::kAllow);
136138

137139
v8::FunctionCallback callback = 0;
138140
v8::Local<v8::External> data;
139141
v8::Local<v8::Signature> signature;
140142

141-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|f!ll", &php_v8_isolate_zv, &fci, &fci_cache, &length, &behavior) ==
142-
FAILURE) {
143+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|f!o!ll", &php_v8_isolate_zv, &fci, &fci_cache, &php_v8_receiver_zv, &length, &behavior) == FAILURE) {
143144
return;
144145
}
145146

@@ -155,6 +156,13 @@ static PHP_METHOD(V8FunctionTemplate, __construct) {
155156

156157
PHP_V8_ENTER_ISOLATE(php_v8_isolate);
157158

159+
if (php_v8_receiver_zv) {
160+
PHP_V8_FETCH_FUNCTION_TEMPLATE_WITH_CHECK(php_v8_receiver_zv, php_v8_receiver);
161+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_function_template, php_v8_receiver);
162+
163+
signature = v8::Signature::New(isolate, php_v8_function_template_get_local(php_v8_receiver));
164+
}
165+
158166
if (fci.size) {
159167
phpv8::CallbacksBucket *bucket= php_v8_function_template->persistent_data->bucket("callback");
160168
data = v8::External::New(isolate, bucket);
@@ -445,6 +453,7 @@ static PHP_METHOD(V8FunctionTemplate, GetExternalAllocatedMemory) {
445453
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_function_template___construct, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
446454
ZEND_ARG_OBJ_INFO(0, isolate, V8\\Isolate, 0)
447455
ZEND_ARG_CALLABLE_INFO(0, callback, 1)
456+
ZEND_ARG_OBJ_INFO(0, receiver, V8\\FunctionTemplate, 1)
448457
ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0)
449458
ZEND_ARG_TYPE_INFO(0, behavior, IS_LONG, 0)
450459
ZEND_END_ARG_INFO()

stubs/src/FunctionTemplate.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,19 @@
118118
class FunctionTemplate extends Template implements AdjustableExternalMemoryInterface
119119
{
120120
/**
121-
* @param Isolate $isolate
122-
* @param callable|null $callback
123-
* @param int $length
124-
* @param int $behavior
121+
* @param Isolate $isolate
122+
* @param callable|null $callback
123+
* @param FunctionTemplate|null $receiver Specifies which receiver is valid for a function
124+
* @param int $length
125+
* @param int $behavior
125126
*/
126-
public function __construct(Isolate $isolate, callable $callback = null, int $length = 0, int $behavior = ConstructorBehavior::kAllow)
127-
{
127+
public function __construct(
128+
Isolate $isolate,
129+
callable $callback = null,
130+
FunctionTemplate $receiver = null,
131+
int $length = 0,
132+
int $behavior = ConstructorBehavior::kAllow
133+
) {
128134
parent::__construct($isolate);
129135
}
130136

tests/.testsuite.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ public function assert($message, $actual, $expected = true, $identical = true)
128128
}
129129
}
130130

131+
public function fail($message = null) {
132+
echo $message ?: 'Should fail', PHP_EOL;
133+
}
134+
131135
public function value_matches($expected, $actual, $identical = true)
132136
{
133137
if ($identical) {

tests/V8FunctionTemplate_constructor_behavior.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ $ftpl_allow = new \V8\FunctionTemplate($isolate, function () {
2525

2626
$ftpl_throw = new \V8\FunctionTemplate($isolate, function () {
2727
echo 'Throw', PHP_EOL;
28-
}, 0, \V8\ConstructorBehavior::kThrow);
28+
}, null, 0, \V8\ConstructorBehavior::kThrow);
2929

3030
$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'f_allow'), $ftpl_allow->GetFunction($context));
3131
$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'f_throw'), $ftpl_throw->GetFunction($context));
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
--TEST--
2+
V8\FunctionTemplate - constructor receiver
3+
--SKIPIF--
4+
<?php if (!extension_loaded("v8")) {
5+
print "skip";
6+
} ?>
7+
--FILE--
8+
<?php
9+
/** @var \Phpv8Testsuite $helper */
10+
$helper = require '.testsuite.php';
11+
require '.v8-helpers.php';
12+
$v8_helper = new PhpV8Helpers($helper);
13+
14+
require '.tracking_dtors.php';
15+
16+
// Tests:
17+
18+
$isolate = new \V8\Isolate();
19+
$context = new \V8\Context($isolate);
20+
$v8_helper->injectConsoleLog($context);
21+
22+
23+
$cb = function (\V8\FunctionCallbackInfo $args) {
24+
echo 'Callback', PHP_EOL;
25+
$args->GetReturnValue()->Set(new \V8\IntegerValue($args->GetIsolate(), 42));
26+
};
27+
28+
$sig_obj = new \V8\FunctionTemplate($isolate);
29+
30+
$x = new \V8\FunctionTemplate($isolate, $cb, $sig_obj);
31+
32+
$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'sig_obj'), $sig_obj->GetFunction($context));
33+
$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'x'), $x->GetFunction($context));
34+
35+
$v8_helper->CompileRun($context, "var s = new sig_obj();");
36+
37+
try {
38+
$v8_helper->CompileRun($context, "x()");
39+
$helper->fail();
40+
}catch (\V8\Exceptions\TryCatchException $e) {
41+
$helper->exception_export($e);
42+
}
43+
44+
try {
45+
$v8_helper->CompileRun($context, "x.call(1)");
46+
$helper->fail();
47+
}catch (\V8\Exceptions\TryCatchException $e) {
48+
$helper->exception_export($e);
49+
}
50+
51+
$res = $v8_helper->CompileRun($context, "s.x = x; s.x()");
52+
$v8_helper->CHECK_EQ(42, $res->Value());
53+
54+
$res = $v8_helper->CompileRun($context, "x.call(s)");
55+
$v8_helper->CHECK_EQ(42, $res->Value());
56+
57+
58+
?>
59+
--EXPECT--
60+
V8\Exceptions\TryCatchException: TypeError: Illegal invocation
61+
V8\Exceptions\TryCatchException: TypeError: Illegal invocation
62+
Callback
63+
CHECK_EQ: OK
64+
Callback
65+
CHECK_EQ: OK

0 commit comments

Comments
 (0)