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

Commit 50d3083

Browse files
committed
Add V8\ConstructorBehavior
1 parent b85e1ed commit 50d3083

13 files changed

+270
-35
lines changed

config.m4

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ if test "$PHP_V8" != "no"; then
166166
src/php_v8_context.cc \
167167
src/php_v8_object_template.cc \
168168
src/php_v8_function_template.cc \
169+
src/php_v8_constructor_behavior.cc \
169170
src/php_v8_script.cc \
170171
src/php_v8_unbound_script.cc \
171172
src/php_v8_cached_data.cc \

src/php_v8_constructor_behavior.cc

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* This file is part of the pinepain/php-v8 PHP extension.
3+
*
4+
* Copyright (c) 2015-2017 Bogdan Padalko <pinepain@gmail.com>
5+
*
6+
* Licensed under the MIT license: http://opensource.org/licenses/MIT
7+
*
8+
* For the full copyright and license information, please view the
9+
* LICENSE file that was distributed with this source or visit
10+
* http://opensource.org/licenses/MIT
11+
*/
12+
13+
#ifdef HAVE_CONFIG_H
14+
#include "config.h"
15+
#endif
16+
17+
#include "php_v8_constructor_behavior.h"
18+
#include "php_v8.h"
19+
20+
zend_class_entry* php_v8_constructor_behavior_class_entry;
21+
#define this_ce php_v8_constructor_behavior_class_entry
22+
23+
24+
static const zend_function_entry php_v8_constructor_behavior_methods[] = {
25+
PHP_FE_END
26+
};
27+
28+
PHP_MINIT_FUNCTION(php_v8_constructor_behavior) {
29+
zend_class_entry ce;
30+
INIT_NS_CLASS_ENTRY(ce, PHP_V8_NS, "ConstructorBehavior", php_v8_constructor_behavior_methods);
31+
this_ce = zend_register_internal_class(&ce);
32+
33+
zend_declare_class_constant_long(this_ce, ZEND_STRL("kThrow"), static_cast<long>(v8::ConstructorBehavior::kThrow));
34+
zend_declare_class_constant_long(this_ce, ZEND_STRL("kAllow"), static_cast<long>(v8::ConstructorBehavior::kAllow));
35+
36+
return SUCCESS;
37+
}

src/php_v8_constructor_behavior.h

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of the pinepain/php-v8 PHP extension.
3+
*
4+
* Copyright (c) 2015-2017 Bogdan Padalko <pinepain@gmail.com>
5+
*
6+
* Licensed under the MIT license: http://opensource.org/licenses/MIT
7+
*
8+
* For the full copyright and license information, please view the
9+
* LICENSE file that was distributed with this source or visit
10+
* http://opensource.org/licenses/MIT
11+
*/
12+
13+
#ifndef PHP_V8_CONSTRUCTOR_BEHAVIOR_H
14+
#define PHP_V8_CONSTRUCTOR_BEHAVIOR_H
15+
16+
#include <v8.h>
17+
18+
extern "C" {
19+
#include "php.h"
20+
21+
#ifdef ZTS
22+
#include "TSRM.h"
23+
#endif
24+
}
25+
26+
extern zend_class_entry* php_v8_constructor_behavior_class_entry;
27+
28+
PHP_MINIT_FUNCTION (php_v8_constructor_behavior);
29+
30+
#define PHP_V8_CONSTRUCTOR_BEHAVIOR_FLAGS ( 0 \
31+
| static_cast<long>(v8::ConstructorBehavior::kAllow) \
32+
| static_cast<long>(v8::ConstructorBehavior::kThrow) \
33+
)
34+
35+
36+
#endif //PHP_V8_CONSTRUCTOR_BEHAVIOR_H

src/php_v8_function.cc

+10-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "php_v8_string.h"
2121
#include "php_v8_object.h"
2222
#include "php_v8_context.h"
23+
#include "php_v8_constructor_behavior.h"
2324
#include "php_v8.h"
2425

2526
zend_class_entry *php_v8_function_class_entry;
@@ -302,14 +303,17 @@ static PHP_METHOD(V8Function, __construct) {
302303
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
303304

304305
zend_long length = 0;
306+
zend_long behavior = static_cast<zend_long>(v8::ConstructorBehavior::kAllow);
305307

306308
v8::FunctionCallback callback = 0;
307309
v8::Local<v8::External> data;
308310

309-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "of|l", &php_v8_context_zv, &fci, &fci_cache, &length) == FAILURE) {
311+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "of|ll", &php_v8_context_zv, &fci, &fci_cache, &length, &behavior) == FAILURE) {
310312
return;
311313
}
312314

315+
behavior = behavior ? behavior & PHP_V8_CONSTRUCTOR_BEHAVIOR_FLAGS : behavior;
316+
313317
PHP_V8_CHECK_FUNCTION_LENGTH_RANGE(length, "Length is out of range");
314318

315319
PHP_V8_VALUE_FETCH_INTO(getThis(), php_v8_value);
@@ -333,7 +337,11 @@ static PHP_METHOD(V8Function, __construct) {
333337
callback = php_v8_callback_function;
334338
}
335339

336-
v8::MaybeLocal<v8::Function> maybe_local_function = v8::Function::New(context, callback, data, static_cast<int>(length));
340+
v8::MaybeLocal<v8::Function> maybe_local_function = v8::Function::New(context,
341+
callback,
342+
data,
343+
static_cast<int>(length),
344+
static_cast<v8::ConstructorBehavior>(behavior));
337345

338346
if (maybe_local_function.IsEmpty()) {
339347
PHP_V8_THROW_EXCEPTION("Failed to create Function value");

src/php_v8_function_template.cc

+12-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "php_v8_value.h"
2323
#include "php_v8_context.h"
2424
#include "php_v8_ext_mem_interface.h"
25+
#include "php_v8_constructor_behavior.h"
2526
#include "php_v8.h"
2627

2728
zend_class_entry *php_v8_function_template_class_entry;
@@ -131,16 +132,19 @@ static PHP_METHOD(V8FunctionTemplate, __construct) {
131132
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
132133

133134
zend_long length = 0;
135+
zend_long behavior = static_cast<zend_long>(v8::ConstructorBehavior::kAllow);
134136

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

139-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|f!l", &php_v8_isolate_zv, &fci, &fci_cache, &length) ==
141+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|f!ll", &php_v8_isolate_zv, &fci, &fci_cache, &length, &behavior) ==
140142
FAILURE) {
141143
return;
142144
}
143145

146+
behavior = behavior ? behavior & PHP_V8_CONSTRUCTOR_BEHAVIOR_FLAGS : behavior;
147+
144148
PHP_V8_CHECK_FUNCTION_LENGTH_RANGE(length, "Length is out of range");
145149

146150
PHP_V8_ISOLATE_FETCH_WITH_CHECK(php_v8_isolate_zv, php_v8_isolate);
@@ -160,7 +164,12 @@ static PHP_METHOD(V8FunctionTemplate, __construct) {
160164
callback = php_v8_callback_function;
161165
}
162166

163-
v8::Local<v8::FunctionTemplate> local_template = v8::FunctionTemplate::New(isolate, callback, data, signature, static_cast<int>(length));
167+
v8::Local<v8::FunctionTemplate> local_template = v8::FunctionTemplate::New(isolate,
168+
callback,
169+
data,
170+
signature,
171+
static_cast<int>(length),
172+
static_cast<v8::ConstructorBehavior>(behavior));
164173

165174
PHP_V8_THROW_VALUE_EXCEPTION_WHEN_EMPTY(local_template, "Failed to create FunctionTemplate value");
166175

@@ -437,6 +446,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_function_template___construct, ZEND_SEND_BY_VA
437446
ZEND_ARG_OBJ_INFO(0, isolate, V8\\Isolate, 0)
438447
ZEND_ARG_CALLABLE_INFO(0, callback, 1)
439448
ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0)
449+
ZEND_ARG_TYPE_INFO(0, behavior, IS_LONG, 0)
440450
ZEND_END_ARG_INFO()
441451

442452
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_v8_function_template_GetIsolate, ZEND_RETURN_VALUE, 0, V8\\Isolate, 0)

stubs/src/ConstructorBehavior.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the pinepain/php-v8 PHP extension.
5+
*
6+
* Copyright (c) 2015-2017 Bogdan Padalko <pinepain@gmail.com>
7+
*
8+
* Licensed under the MIT license: http://opensource.org/licenses/MIT
9+
*
10+
* For the full copyright and license information, please view the
11+
* LICENSE file that was distributed with this source or visit
12+
* http://opensource.org/licenses/MIT
13+
*/
14+
15+
16+
namespace V8;
17+
18+
19+
class ConstructorBehavior
20+
{
21+
const kThrow = 0;
22+
const kAllow = 1;
23+
}

stubs/src/FunctionObject.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ class FunctionObject extends ObjectValue
2828
* @param \V8\Context $context
2929
* @param callable $callback
3030
* @param int $length
31+
* @param int $behavior
3132
*/
32-
public function __construct(Context $context, callable $callback, int $length = 0)
33+
public function __construct(Context $context, callable $callback, int $length = 0, int $behavior = ConstructorBehavior::kAllow)
3334
{
3435
parent::__construct($context);
3536
}

stubs/src/FunctionTemplate.php

+19-23
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* preferred.
2626
*
2727
* Any modification of a FunctionTemplate after first instantiation will trigger
28-
*a crash.
28+
* a crash.
2929
*
3030
* A FunctionTemplate can have properties, these properties are added to the
3131
* function object when it is created.
@@ -41,17 +41,21 @@
4141
* The following example shows how to use a FunctionTemplate:
4242
*
4343
* \code
44-
* v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
45-
* t->Set("func_property", v8::Number::New(1));
44+
* v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
45+
* t->Set(isolate, "func_property", v8::Number::New(isolate, 1));
4646
*
4747
* v8::Local<v8::Template> proto_t = t->PrototypeTemplate();
48-
* proto_t->Set("proto_method", v8::FunctionTemplate::New(InvokeCallback));
49-
* proto_t->Set("proto_const", v8::Number::New(2));
48+
* proto_t->Set(isolate,
49+
* "proto_method",
50+
* v8::FunctionTemplate::New(isolate, InvokeCallback));
51+
* proto_t->Set(isolate, "proto_const", v8::Number::New(isolate, 2));
5052
*
5153
* v8::Local<v8::ObjectTemplate> instance_t = t->InstanceTemplate();
52-
* instance_t->SetAccessor("instance_accessor", InstanceAccessorCallback);
53-
* instance_t->SetNamedPropertyHandler(PropertyHandlerCallback, ...);
54-
* instance_t->Set("instance_property", Number::New(3));
54+
* instance_t->SetAccessor(String::NewFromUtf8(isolate, "instance_accessor"),
55+
* InstanceAccessorCallback);
56+
* instance_t->SetNamedPropertyHandler(PropertyHandlerCallback);
57+
* instance_t->Set(String::NewFromUtf8(isolate, "instance_property"),
58+
* Number::New(isolate, 3));
5559
*
5660
* v8::Local<v8::Function> function = t->GetFunction();
5761
* v8::Local<v8::Object> instance = function->NewInstance();
@@ -111,27 +115,19 @@
111115
* child_instance.instance_property == 3;
112116
* \endcode
113117
*/
114-
//class FunctionTemplateInterface extends TemplateInterface
115118
class FunctionTemplate extends Template implements AdjustableExternalMemoryInterface
116119
{
117-
private $isolate;
118-
119-
//static Local<FunctionTemplate> New(
120-
// Isolate* isolate,
121-
// FunctionCallback callback = 0,
122-
// Handle<Value> data = Handle<Value>(),
123-
// Handle<Signature> signature = Handle<Signature>(),
124-
// int length = 0);
125-
public function __construct(Isolate $isolate, callable $callback = null, int $length = 0)
120+
/**
121+
* @param Isolate $isolate
122+
* @param callable|null $callback
123+
* @param int $length
124+
* @param int $behavior
125+
*/
126+
public function __construct(Isolate $isolate, callable $callback = null, int $length = 0, int $behavior = ConstructorBehavior::kAllow)
126127
{
127128
parent::__construct($isolate);
128129
}
129130

130-
public function GetIsolate()
131-
{
132-
return $this->isolate;
133-
}
134-
135131
/**
136132
* Returns the unique function instance in the current execution context.
137133
*

tests/V8ConstructorBehavior.phpt

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
V8\ConstructorBehavior
3+
--SKIPIF--
4+
<?php if (!extension_loaded("v8")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
8+
// Bootstraps:
9+
$obj = new V8\ConstructorBehavior();
10+
11+
// Tests:
12+
13+
/** @var \Phpv8Testsuite $helper */
14+
$helper = require '.testsuite.php';
15+
16+
$helper->header('Object representation');
17+
$helper->dump($obj);
18+
$helper->space();
19+
20+
21+
$helper->header('Class constants');
22+
$helper->dump_object_constants($obj);
23+
$helper->space();
24+
25+
?>
26+
--EXPECT--
27+
Object representation:
28+
----------------------
29+
object(V8\ConstructorBehavior)#1 (0) {
30+
}
31+
32+
33+
Class constants:
34+
----------------
35+
V8\ConstructorBehavior::kThrow = 0
36+
V8\ConstructorBehavior::kAllow = 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
V8\FunctionObject - constructor behavior
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+
$f_allow = new \V8\FunctionObject($context, function () {
23+
echo 'Allow', PHP_EOL;
24+
});
25+
26+
$f_throw = new \V8\FunctionObject($context, function () {
27+
echo 'Throw', PHP_EOL;
28+
}, 0, \V8\ConstructorBehavior::kThrow);
29+
30+
$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'f_allow'), $f_allow);
31+
$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'f_throw'), $f_throw);
32+
33+
34+
$v8_helper->CompileRun($context, 'f_allow(); new f_allow();');
35+
try {
36+
$v8_helper->CompileRun($context, 'f_throw(); new f_throw();');
37+
} catch (\V8\Exceptions\TryCatchException $e) {
38+
$helper->exception_export($e);
39+
}
40+
41+
?>
42+
--EXPECT--
43+
Allow
44+
Allow
45+
Throw
46+
V8\Exceptions\TryCatchException: TypeError: f_throw is not a constructor

tests/V8FunctionTemplate.phpt

-7
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ $helper->dump($instance_template);
7373
$helper->method_matches($function_template, 'InstanceTemplate', $instance_template);
7474
$helper->space();
7575

76-
$instance_template_1 = $function_template->InstanceTemplate();
77-
78-
$instance_template_2 = $function_template->InstanceTemplate();
79-
8076
$global_template = new V8\ObjectTemplate($isolate);
8177

8278
$value = new V8\StringValue($isolate, 'TEST VALUE 111');
@@ -138,9 +134,6 @@ if ($res->IsFunction()) {
138134
$helper->dump($res->ToString($context)->Value());
139135

140136

141-
142-
143-
144137
?>
145138
--EXPECT--
146139
Object representation:

0 commit comments

Comments
 (0)