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

Commit 9b1cdac

Browse files
committed
Add V8\ScriptCompiler\CachedData class
1 parent 299adae commit 9b1cdac

File tree

7 files changed

+309
-0
lines changed

7 files changed

+309
-0
lines changed

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ if test "$PHP_V8" != "no"; then
168168
src/php_v8_function_template.cc \
169169
src/php_v8_script.cc \
170170
src/php_v8_unbound_script.cc \
171+
src/php_v8_cached_data.cc \
171172
src/php_v8_data.cc \
172173
src/php_v8_value.cc \
173174
src/php_v8_primitive.cc \

src/php_v8_cached_data.cc

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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_cached_data.h"
18+
#include "php_v8_string.h"
19+
#include "php_v8.h"
20+
21+
22+
zend_class_entry * php_v8_cached_data_class_entry;
23+
#define this_ce php_v8_cached_data_class_entry
24+
25+
static zend_object_handlers php_v8_cached_data_object_handlers;
26+
27+
php_v8_cached_data_t * php_v8_cached_data_fetch_object(zend_object *obj) {
28+
return (php_v8_cached_data_t *)((char *)obj - XtOffsetOf(php_v8_cached_data_t, std));
29+
}
30+
31+
php_v8_cached_data_t * php_v8_create_cached_data(zval *return_value, const v8::ScriptCompiler::CachedData *cached_data) {
32+
33+
object_init_ex(return_value, this_ce);
34+
PHP_V8_FETCH_CACHED_DATA_INTO(return_value, php_v8_cached_data);
35+
36+
int length = cached_data->length;
37+
uint8_t* data = new uint8_t[length];
38+
memcpy(data, cached_data->data, static_cast<size_t>(length));
39+
40+
php_v8_cached_data->cached_data = new v8::ScriptCompiler::CachedData(data, length, v8::ScriptCompiler::CachedData::BufferPolicy::BufferOwned);
41+
42+
return php_v8_cached_data;
43+
}
44+
45+
static void php_v8_cached_data_free(zend_object *object)
46+
{
47+
php_v8_cached_data_t *php_v8_cached_data = php_v8_cached_data_fetch_object(object);
48+
49+
if (php_v8_cached_data->cached_data) {
50+
delete php_v8_cached_data->cached_data;
51+
}
52+
53+
zend_object_std_dtor(&php_v8_cached_data->std);
54+
}
55+
56+
static zend_object * php_v8_cached_data_ctor(zend_class_entry *ce)
57+
{
58+
php_v8_cached_data_t *php_v8_cached_data;
59+
60+
php_v8_cached_data = (php_v8_cached_data_t *) ecalloc(1, sizeof(php_v8_cached_data_t) + zend_object_properties_size(ce));
61+
62+
zend_object_std_init(&php_v8_cached_data->std, ce);
63+
object_properties_init(&php_v8_cached_data->std, ce);
64+
65+
php_v8_cached_data->std.handlers = &php_v8_cached_data_object_handlers;
66+
67+
return &php_v8_cached_data->std;
68+
}
69+
70+
static PHP_METHOD(V8CachedData, __construct)
71+
{
72+
zend_string *string = NULL;
73+
74+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &string) == FAILURE) {
75+
return;
76+
}
77+
78+
PHP_V8_CHECK_CACHE_DATA_STRING_RANGE(string, "CachedData data string is too long");
79+
80+
PHP_V8_FETCH_CACHED_DATA_INTO(getThis(), php_v8_cached_data);
81+
82+
int length = static_cast<int>(MAYBE_ZSTR_LEN(string));
83+
uint8_t* data = new uint8_t[length];
84+
memcpy(data, MAYBE_ZSTR_VAL(string), static_cast<size_t>(length));
85+
86+
php_v8_cached_data->cached_data = new v8::ScriptCompiler::CachedData(data, length, v8::ScriptCompiler::CachedData::BufferPolicy::BufferOwned);
87+
}
88+
89+
static PHP_METHOD(V8CachedData, GetData)
90+
{
91+
if (zend_parse_parameters_none() == FAILURE) {
92+
return;
93+
}
94+
95+
PHP_V8_FETCH_CACHED_DATA_WITH_CHECK(getThis(), php_v8_cached_data);
96+
97+
RETVAL_STRINGL(reinterpret_cast<const char*>(php_v8_cached_data->cached_data->data), php_v8_cached_data->cached_data->length);
98+
}
99+
100+
static PHP_METHOD(V8CachedData, IsRejected)
101+
{
102+
if (zend_parse_parameters_none() == FAILURE) {
103+
return;
104+
}
105+
106+
PHP_V8_FETCH_CACHED_DATA_WITH_CHECK(getThis(), php_v8_cached_data);
107+
108+
RETVAL_BOOL(php_v8_cached_data->cached_data->rejected);
109+
}
110+
111+
112+
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_cached_data___construct, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
113+
ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
114+
ZEND_END_ARG_INFO()
115+
116+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_cached_data_GetData, ZEND_RETURN_VALUE, 0, IS_STRING, 0)
117+
ZEND_END_ARG_INFO()
118+
119+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_cached_data_IsRejected, ZEND_RETURN_VALUE, 0, _IS_BOOL, 0)
120+
ZEND_END_ARG_INFO()
121+
122+
123+
static const zend_function_entry php_v8_cached_data_methods[] = {
124+
PHP_ME(V8CachedData, __construct, arginfo_v8_cached_data___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
125+
PHP_ME(V8CachedData, GetData, arginfo_v8_cached_data_GetData, ZEND_ACC_PUBLIC)
126+
PHP_ME(V8CachedData, IsRejected, arginfo_v8_cached_data_IsRejected, ZEND_ACC_PUBLIC)
127+
128+
PHP_FE_END
129+
};
130+
131+
132+
PHP_MINIT_FUNCTION(php_v8_cached_data)
133+
{
134+
zend_class_entry ce;
135+
136+
INIT_NS_CLASS_ENTRY(ce, "V8\\ScriptCompiler", "CachedData", php_v8_cached_data_methods);
137+
this_ce = zend_register_internal_class(&ce);
138+
this_ce->create_object = php_v8_cached_data_ctor;
139+
140+
memcpy(&php_v8_cached_data_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
141+
142+
php_v8_cached_data_object_handlers.offset = XtOffsetOf(php_v8_cached_data_t, std);
143+
php_v8_cached_data_object_handlers.free_obj = php_v8_cached_data_free;
144+
145+
return SUCCESS;
146+
}

src/php_v8_cached_data.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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_CACHED_DATA_H
14+
#define PHP_V8_CACHED_DATA_H
15+
16+
typedef struct _php_v8_cached_data_t php_v8_cached_data_t;
17+
18+
#include "php_v8_exceptions.h"
19+
#include <v8.h>
20+
21+
extern "C" {
22+
#include "php.h"
23+
24+
#ifdef ZTS
25+
#include "TSRM.h"
26+
#endif
27+
}
28+
29+
extern zend_class_entry *php_v8_cached_data_class_entry;
30+
31+
extern php_v8_cached_data_t * php_v8_cached_data_fetch_object(zend_object *obj);
32+
extern php_v8_cached_data_t * php_v8_create_cached_data(zval *return_value, const v8::ScriptCompiler::CachedData *cached_data);
33+
34+
35+
#define PHP_V8_FETCH_CACHED_DATA(zv) php_v8_cached_data_fetch_object(Z_OBJ_P(zv))
36+
#define PHP_V8_FETCH_CACHED_DATA_INTO(pzval, into) php_v8_cached_data_t *(into) = PHP_V8_FETCH_CACHED_DATA((pzval))
37+
38+
#define PHP_V8_EMPTY_CACHED_DATA_MSG "CachedData" PHP_V8_EMPTY_HANDLER_MSG_PART
39+
#define PHP_V8_CHECK_EMPTY_CACHED_DATA_HANDLER(val) if (NULL == (val)->cached_data) { PHP_V8_THROW_EXCEPTION( PHP_V8_EMPTY_CACHED_DATA_MSG); return; }
40+
41+
42+
#define PHP_V8_FETCH_CACHED_DATA_WITH_CHECK(pzval, into) \
43+
PHP_V8_FETCH_CACHED_DATA_INTO(pzval, into); \
44+
PHP_V8_CHECK_EMPTY_CACHED_DATA_HANDLER(into);
45+
46+
47+
#define PHP_V8_CHECK_CACHE_DATA_STRING_RANGE(str, message) \
48+
if (MAYBE_ZSTR_LEN(str) > INT_MAX) { \
49+
PHP_V8_THROW_VALUE_EXCEPTION(message); \
50+
return; \
51+
}
52+
53+
54+
struct _php_v8_cached_data_t {
55+
v8::ScriptCompiler::CachedData *cached_data;
56+
57+
zend_object std;
58+
};
59+
60+
PHP_MINIT_FUNCTION(php_v8_cached_data);
61+
62+
#endif //PHP_V8_CACHED_DATA_H
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
4+
namespace V8\ScriptCompiler;
5+
6+
7+
/**
8+
* Compilation data that the embedder can cache and pass back to speed up
9+
* future compilations. The data is produced if the CompilerOptions passed to
10+
* the compilation functions in ScriptCompiler contains produce_data_to_cache
11+
* = true. The data to cache can then can be retrieved from
12+
* UnboundScript.
13+
*/
14+
class CachedData
15+
{
16+
public function __construct(string $data)
17+
{
18+
}
19+
20+
public function getData(): string
21+
{
22+
}
23+
24+
// TODO: technically, we can use \strlen($this->getData()) when we need, though in PHP it's not necessary to get string length before fetching string itself
25+
//public function getLength(): int
26+
//{
27+
//}
28+
29+
public function isRejected(): bool
30+
{
31+
}
32+
}

tests/.testsuite.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ public function method_matches_with_output($object, $method, $expected, array $a
197197
true), PHP_EOL;
198198
}
199199

200+
public function method_matches_with_dump($object, $method, $expected, array $args = [])
201+
{
202+
echo get_class($object), '::', $method, '()', ' ', ($expected === $object->$method(...$args) ? 'matches' : 'doesn\'t match'), ' expected ';
203+
$this->dump($expected);
204+
}
205+
200206
public function method_dump($object, $method, array $args = [])
201207
{
202208
echo get_class($object), '::', $method, '()', ' ', var_export($object->$method(...$args), true), PHP_EOL;

tests/V8CachedData.phpt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
--TEST--
2+
V8\ScriptCompiler\CachedData
3+
--SKIPIF--
4+
<?php if (!extension_loaded("v8")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
8+
/** @var \Phpv8Testsuite $helper */
9+
$helper = require '.testsuite.php';
10+
11+
require '.v8-helpers.php';
12+
$v8_helper = new PhpV8Helpers($helper);
13+
14+
// Tests:
15+
16+
$value = new \V8\ScriptCompiler\CachedData('');
17+
18+
$helper->header('Object representation');
19+
$helper->dump($value);
20+
$helper->space();
21+
22+
$helper->header('Methods');
23+
24+
$data = [
25+
'',
26+
'test foo bar baz',
27+
random_bytes(16),
28+
random_bytes(31),
29+
'Юникод',
30+
'萬國碼、國際碼、統一碼、單一碼',
31+
'یوونیکۆد',
32+
];
33+
34+
foreach ($data as $d) {
35+
$value = new \V8\ScriptCompiler\CachedData($d);
36+
$helper->method_matches_with_dump($value, 'GetData', $d);
37+
}
38+
39+
$helper->method_dump($value, 'IsRejected');
40+
41+
42+
43+
?>
44+
--EXPECTF--
45+
Object representation:
46+
----------------------
47+
object(V8\ScriptCompiler\CachedData)#3 (0) {
48+
}
49+
50+
51+
Methods:
52+
--------
53+
V8\ScriptCompiler\CachedData::GetData() matches expected string(0) ""
54+
V8\ScriptCompiler\CachedData::GetData() matches expected string(16) "test foo bar baz"
55+
V8\ScriptCompiler\CachedData::GetData() matches expected string(16) "%r.{16}%r"
56+
V8\ScriptCompiler\CachedData::GetData() matches expected string(31) "%r.{31}%r"
57+
V8\ScriptCompiler\CachedData::GetData() matches expected string(12) "Юникод"
58+
V8\ScriptCompiler\CachedData::GetData() matches expected string(45) "萬國碼、國際碼、統一碼、單一碼"
59+
V8\ScriptCompiler\CachedData::GetData() matches expected string(16) "یوونیکۆد"
60+
V8\ScriptCompiler\CachedData::IsRejected() false

v8.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "php_v8_function_template.h"
3333
#include "php_v8_script.h"
3434
#include "php_v8_unbound_script.h"
35+
#include "php_v8_cached_data.h"
3536
#include "php_v8_null.h"
3637
#include "php_v8_boolean.h"
3738
#include "php_v8_symbol.h"
@@ -108,6 +109,7 @@ PHP_MINIT_FUNCTION(v8)
108109
PHP_MINIT(php_v8_context)(INIT_FUNC_ARGS_PASSTHRU);
109110
PHP_MINIT(php_v8_script)(INIT_FUNC_ARGS_PASSTHRU);
110111
PHP_MINIT(php_v8_unbound_script)(INIT_FUNC_ARGS_PASSTHRU);
112+
PHP_MINIT(php_v8_cached_data)(INIT_FUNC_ARGS_PASSTHRU);
111113

112114
PHP_MINIT(php_v8_exception)(INIT_FUNC_ARGS_PASSTHRU);
113115
PHP_MINIT(php_v8_try_catch)(INIT_FUNC_ARGS_PASSTHRU);

0 commit comments

Comments
 (0)