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

Commit 120a4dc

Browse files
authored
Merge pull request #66 from pinepain/add-missed-builtin
Refactor to simplify public API
2 parents 22b33a1 + 4903093 commit 120a4dc

30 files changed

+1765
-155
lines changed

config.m4

+2
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ if test "$PHP_V8" != "no"; then
203203
src/php_v8_set.cc \
204204
src/php_v8_date.cc \
205205
src/php_v8_regexp.cc \
206+
src/php_v8_promise.cc \
207+
src/php_v8_proxy.cc \
206208
src/php_v8_number_object.cc \
207209
src/php_v8_boolean_object.cc \
208210
src/php_v8_string_object.cc \

src/php_v8_isolate.cc

+42-18
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,21 @@ static PHP_METHOD(Isolate, isMemoryLimitHit) {
296296
RETVAL_BOOL(php_v8_isolate->limits.memory_limit_hit);
297297
}
298298

299+
static PHP_METHOD(Isolate, memoryPressureNotification) {
300+
zend_long level = static_cast<zend_long>(v8::MemoryPressureLevel::kNone);
301+
302+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &level) == FAILURE) {
303+
return;
304+
}
305+
306+
PHP_V8_CHECK_ISOLATE_MEMORY_PRESSURE_LEVEL(level, "Invalid memory pressure level given. See V8\\Isolate MEMORY_PRESSURE_LEVEL_* class constants for available levels.")
307+
308+
PHP_V8_ISOLATE_FETCH_WITH_CHECK(getThis(), php_v8_isolate);
309+
PHP_V8_ENTER_ISOLATE(php_v8_isolate);
310+
311+
isolate->MemoryPressureNotification(static_cast<v8::MemoryPressureLevel>(level));
312+
}
313+
299314
static PHP_METHOD(Isolate, getHeapStatistics) {
300315
if (zend_parse_parameters_none() == FAILURE) {
301316
return;
@@ -511,6 +526,10 @@ ZEND_END_ARG_INFO()
511526
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_isMemoryLimitHit, ZEND_RETURN_VALUE, 0, _IS_BOOL, 0)
512527
ZEND_END_ARG_INFO()
513528

529+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_VOID_INFO_EX(arginfo_memoryPressureNotification, 0)
530+
ZEND_ARG_TYPE_INFO(0, level, IS_LONG, 0)
531+
ZEND_END_ARG_INFO()
532+
514533
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_getHeapStatistics, ZEND_RETURN_VALUE, 0, V8\\HeapStatistics, 0)
515534
ZEND_END_ARG_INFO()
516535

@@ -555,24 +574,25 @@ ZEND_END_ARG_INFO()
555574

556575

557576
static const zend_function_entry php_v8_isolate_methods[] = {
558-
PHP_V8_ME(Isolate, __construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
559-
PHP_V8_ME(Isolate, setTimeLimit, ZEND_ACC_PUBLIC)
560-
PHP_V8_ME(Isolate, getTimeLimit, ZEND_ACC_PUBLIC)
561-
PHP_V8_ME(Isolate, isTimeLimitHit, ZEND_ACC_PUBLIC)
562-
PHP_V8_ME(Isolate, setMemoryLimit, ZEND_ACC_PUBLIC)
563-
PHP_V8_ME(Isolate, getMemoryLimit, ZEND_ACC_PUBLIC)
564-
PHP_V8_ME(Isolate, isMemoryLimitHit, ZEND_ACC_PUBLIC)
565-
PHP_V8_ME(Isolate, getHeapStatistics, ZEND_ACC_PUBLIC)
566-
PHP_V8_ME(Isolate, inContext, ZEND_ACC_PUBLIC)
567-
PHP_V8_ME(Isolate, getEnteredContext, ZEND_ACC_PUBLIC)
568-
PHP_V8_ME(Isolate, throwException, ZEND_ACC_PUBLIC)
569-
PHP_V8_ME(Isolate, idleNotificationDeadline, ZEND_ACC_PUBLIC)
570-
PHP_V8_ME(Isolate, lowMemoryNotification, ZEND_ACC_PUBLIC)
571-
PHP_V8_ME(Isolate, terminateExecution, ZEND_ACC_PUBLIC)
572-
PHP_V8_ME(Isolate, isExecutionTerminating, ZEND_ACC_PUBLIC)
573-
PHP_V8_ME(Isolate, cancelTerminateExecution, ZEND_ACC_PUBLIC)
574-
PHP_V8_ME(Isolate, isDead, ZEND_ACC_PUBLIC)
575-
PHP_V8_ME(Isolate, isInUse, ZEND_ACC_PUBLIC)
577+
PHP_V8_ME(Isolate, __construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
578+
PHP_V8_ME(Isolate, setTimeLimit, ZEND_ACC_PUBLIC)
579+
PHP_V8_ME(Isolate, getTimeLimit, ZEND_ACC_PUBLIC)
580+
PHP_V8_ME(Isolate, isTimeLimitHit, ZEND_ACC_PUBLIC)
581+
PHP_V8_ME(Isolate, setMemoryLimit, ZEND_ACC_PUBLIC)
582+
PHP_V8_ME(Isolate, getMemoryLimit, ZEND_ACC_PUBLIC)
583+
PHP_V8_ME(Isolate, isMemoryLimitHit, ZEND_ACC_PUBLIC)
584+
PHP_V8_ME(Isolate, memoryPressureNotification, ZEND_ACC_PUBLIC)
585+
PHP_V8_ME(Isolate, getHeapStatistics, ZEND_ACC_PUBLIC)
586+
PHP_V8_ME(Isolate, inContext, ZEND_ACC_PUBLIC)
587+
PHP_V8_ME(Isolate, getEnteredContext, ZEND_ACC_PUBLIC)
588+
PHP_V8_ME(Isolate, throwException, ZEND_ACC_PUBLIC)
589+
PHP_V8_ME(Isolate, idleNotificationDeadline, ZEND_ACC_PUBLIC)
590+
PHP_V8_ME(Isolate, lowMemoryNotification, ZEND_ACC_PUBLIC)
591+
PHP_V8_ME(Isolate, terminateExecution, ZEND_ACC_PUBLIC)
592+
PHP_V8_ME(Isolate, isExecutionTerminating, ZEND_ACC_PUBLIC)
593+
PHP_V8_ME(Isolate, cancelTerminateExecution, ZEND_ACC_PUBLIC)
594+
PHP_V8_ME(Isolate, isDead, ZEND_ACC_PUBLIC)
595+
PHP_V8_ME(Isolate, isInUse, ZEND_ACC_PUBLIC)
576596
PHP_V8_ME(Isolate, setCaptureStackTraceForUncaughtExceptions, ZEND_ACC_PUBLIC)
577597

578598
PHP_FE_END
@@ -586,6 +606,10 @@ PHP_MINIT_FUNCTION (php_v8_isolate) {
586606
this_ce = zend_register_internal_class(&ce);
587607
this_ce->create_object = php_v8_isolate_ctor;
588608

609+
zend_declare_class_constant_long(this_ce, ZEND_STRL("MEMORY_PRESSURE_LEVEL_NONE"), static_cast<zend_long>(v8::MemoryPressureLevel::kNone));
610+
zend_declare_class_constant_long(this_ce, ZEND_STRL("MEMORY_PRESSURE_LEVEL_MODERATE"), static_cast<zend_long>(v8::MemoryPressureLevel::kModerate));
611+
zend_declare_class_constant_long(this_ce, ZEND_STRL("MEMORY_PRESSURE_LEVEL_CRITICAL"), static_cast<zend_long>(v8::MemoryPressureLevel::kCritical));
612+
589613
memcpy(&php_v8_isolate_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
590614

591615
php_v8_isolate_object_handlers.offset = XtOffsetOf(php_v8_isolate_t, std);

src/php_v8_isolate.h

+6
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ inline v8::Local<v8::Private> php_v8_isolate_get_key_local(php_v8_isolate_t *php
115115
return; \
116116
} \
117117

118+
#define PHP_V8_CHECK_ISOLATE_MEMORY_PRESSURE_LEVEL(level, message) \
119+
if (level < static_cast<zend_long>(v8::MemoryPressureLevel::kNone) \
120+
|| level > static_cast<zend_long>(v8::MemoryPressureLevel::kCritical)) { \
121+
PHP_V8_THROW_VALUE_EXCEPTION(message); \
122+
return; \
123+
}
118124

119125

120126
struct _php_v8_isolate_t {

src/php_v8_promise.cc

+266
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/*
2+
* This file is part of the pinepain/php-v8 PHP extension.
3+
*
4+
* Copyright (c) 2015-2017 Bogdan Padalko <[email protected]>
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_promise.h"
18+
#include "php_v8_object.h"
19+
#include "php_v8_string.h"
20+
#include "php_v8_value.h"
21+
#include "php_v8_context.h"
22+
#include "php_v8.h"
23+
24+
zend_class_entry *php_v8_promise_class_entry;
25+
26+
#define this_ce php_v8_promise_class_entry
27+
28+
29+
static PHP_METHOD(Promise, __construct) {
30+
zval rv;
31+
zval *php_v8_context_zv;
32+
33+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &php_v8_context_zv) == FAILURE) {
34+
return;
35+
}
36+
37+
PHP_V8_OBJECT_CONSTRUCT(getThis(), php_v8_context_zv, php_v8_context, php_v8_value);
38+
39+
v8::MaybeLocal<v8::Promise::Resolver> maybe_local_resolver = v8::Promise::Resolver::New(context);
40+
41+
PHP_V8_THROW_VALUE_EXCEPTION_WHEN_EMPTY(maybe_local_resolver, "Failed to create Promise object");
42+
43+
// under the v8 hood v8::Promise::Resolver and v8::Promise are interchangable (with cast)
44+
v8::Local<v8::Promise::Resolver> local_resolver = maybe_local_resolver.ToLocalChecked();
45+
php_v8_object_store_self_ptr(php_v8_value, local_resolver);
46+
47+
php_v8_value->persistent->Reset(isolate, local_resolver);
48+
}
49+
50+
static PHP_METHOD(Promise, resolve) {
51+
zval *php_v8_context_zv;
52+
zval *php_v8_rvalue_zv;
53+
54+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "oo", &php_v8_context_zv, &php_v8_rvalue_zv) == FAILURE) {
55+
return;
56+
}
57+
58+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
59+
PHP_V8_CONTEXT_FETCH_WITH_CHECK(php_v8_context_zv, php_v8_context);
60+
PHP_V8_VALUE_FETCH_WITH_CHECK(php_v8_rvalue_zv, php_v8_rvalue);
61+
62+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_context);
63+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_rvalue);
64+
65+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
66+
PHP_V8_ENTER_CONTEXT(php_v8_context);
67+
68+
v8::Local<v8::Promise::Resolver> local_resolver = php_v8_value_get_local_as<v8::Promise::Resolver>(php_v8_value);
69+
v8::Local<v8::Value> local_rvalue = php_v8_value_get_local_as<v8::Value>(php_v8_rvalue);
70+
71+
v8::Maybe<bool> maybe_resolved = local_resolver->Resolve(context, local_rvalue);
72+
73+
PHP_V8_THROW_VALUE_EXCEPTION_WHEN_NOTHING(maybe_resolved, "Failed to resolve a promise");
74+
}
75+
76+
static PHP_METHOD(Promise, reject) {
77+
zval *php_v8_context_zv;
78+
zval *php_v8_rvalue_zv;
79+
80+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "oo", &php_v8_context_zv, &php_v8_rvalue_zv) == FAILURE) {
81+
return;
82+
}
83+
84+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
85+
PHP_V8_CONTEXT_FETCH_WITH_CHECK(php_v8_context_zv, php_v8_context);
86+
PHP_V8_VALUE_FETCH_WITH_CHECK(php_v8_rvalue_zv, php_v8_rvalue);
87+
88+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_context);
89+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_rvalue);
90+
91+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
92+
PHP_V8_ENTER_CONTEXT(php_v8_context);
93+
94+
v8::Local<v8::Promise::Resolver> local_resolver = php_v8_value_get_local_as<v8::Promise::Resolver>(php_v8_value);
95+
v8::Local<v8::Value> local_rvalue = php_v8_value_get_local_as<v8::Value>(php_v8_rvalue);
96+
97+
v8::Maybe<bool> maybe_rejected = local_resolver->Reject(context, local_rvalue);
98+
99+
PHP_V8_THROW_VALUE_EXCEPTION_WHEN_NOTHING(maybe_rejected, "Failed to reject a promise");
100+
}
101+
102+
static PHP_METHOD(Promise, catch) {
103+
zval *php_v8_context_zv;
104+
zval *php_v8_function_zv;
105+
106+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "oo", &php_v8_context_zv, &php_v8_function_zv) == FAILURE) {
107+
return;
108+
}
109+
110+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
111+
PHP_V8_CONTEXT_FETCH_WITH_CHECK(php_v8_context_zv, php_v8_context);
112+
PHP_V8_VALUE_FETCH_WITH_CHECK(php_v8_function_zv, php_v8_function);
113+
114+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_context);
115+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_function);
116+
117+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
118+
PHP_V8_ENTER_CONTEXT(php_v8_context);
119+
120+
v8::Local<v8::Promise> local_promise = php_v8_value_get_local_as<v8::Promise>(php_v8_value);
121+
v8::Local<v8::Function> local_function = php_v8_value_get_local_as<v8::Function>(php_v8_function);
122+
123+
v8::MaybeLocal<v8::Promise> maybe_local_promise = local_promise->Catch(context, local_function);
124+
125+
PHP_V8_THROW_VALUE_EXCEPTION_WHEN_EMPTY(maybe_local_promise, "Failed to register rejection handler with a promise");
126+
127+
php_v8_get_or_create_value(return_value, maybe_local_promise.ToLocalChecked(), php_v8_context->php_v8_isolate);
128+
}
129+
130+
static PHP_METHOD(Promise, then) {
131+
zval *php_v8_context_zv;
132+
zval *php_v8_function_zv;
133+
134+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "oo", &php_v8_context_zv, &php_v8_function_zv) == FAILURE) {
135+
return;
136+
}
137+
138+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
139+
PHP_V8_CONTEXT_FETCH_WITH_CHECK(php_v8_context_zv, php_v8_context);
140+
PHP_V8_VALUE_FETCH_WITH_CHECK(php_v8_function_zv, php_v8_function);
141+
142+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_context);
143+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_function);
144+
145+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
146+
PHP_V8_ENTER_CONTEXT(php_v8_context);
147+
148+
v8::Local<v8::Promise> local_promise = php_v8_value_get_local_as<v8::Promise>(php_v8_value);
149+
v8::Local<v8::Function> local_function = php_v8_value_get_local_as<v8::Function>(php_v8_function);
150+
151+
v8::MaybeLocal<v8::Promise> maybe_local_promise = local_promise->Then(context, local_function);
152+
153+
PHP_V8_THROW_VALUE_EXCEPTION_WHEN_EMPTY(maybe_local_promise, "Failed to register resolution handler with a promise");
154+
155+
php_v8_get_or_create_value(return_value, maybe_local_promise.ToLocalChecked(), php_v8_context->php_v8_isolate);
156+
}
157+
158+
static PHP_METHOD(Promise, hasHandler) {
159+
if (zend_parse_parameters_none() == FAILURE) {
160+
return;
161+
}
162+
163+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
164+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
165+
PHP_V8_ENTER_STORED_CONTEXT(php_v8_value);
166+
167+
v8::Local<v8::Promise> local_promise = php_v8_value_get_local_as<v8::Promise>(php_v8_value);
168+
169+
RETURN_BOOL(static_cast<zend_bool>(local_promise->HasHandler()));
170+
}
171+
172+
static PHP_METHOD(Promise, result) {
173+
if (zend_parse_parameters_none() == FAILURE) {
174+
return;
175+
}
176+
177+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
178+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
179+
PHP_V8_ENTER_STORED_CONTEXT(php_v8_value);
180+
181+
v8::Local<v8::Promise> local_promise = php_v8_value_get_local_as<v8::Promise>(php_v8_value);
182+
183+
if (v8::Promise::PromiseState::kPending == local_promise->State()) {
184+
PHP_V8_THROW_VALUE_EXCEPTION("Promise is in pending state");
185+
return;
186+
}
187+
188+
v8::Local<v8::Value> local_value = local_promise->Result();
189+
190+
php_v8_get_or_create_value(return_value, local_value, php_v8_value->php_v8_isolate);
191+
}
192+
193+
static PHP_METHOD(Promise, state) {
194+
if (zend_parse_parameters_none() == FAILURE) {
195+
return;
196+
}
197+
198+
PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value);
199+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_value);
200+
PHP_V8_ENTER_STORED_CONTEXT(php_v8_value);
201+
202+
v8::Local<v8::Promise> local_promise = php_v8_value_get_local_as<v8::Promise>(php_v8_value);
203+
204+
RETURN_LONG(static_cast<zend_long>(local_promise->State()));
205+
}
206+
207+
208+
PHP_V8_ZEND_BEGIN_ARG_WITH_CONSTRUCTOR_INFO_EX(arginfo___construct, 1)
209+
ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0)
210+
ZEND_END_ARG_INFO()
211+
212+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_VOID_INFO_EX(arginfo_resolve, 2)
213+
ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0)
214+
ZEND_ARG_OBJ_INFO(0, value, V8\\Value, 0)
215+
ZEND_END_ARG_INFO()
216+
217+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_VOID_INFO_EX(arginfo_reject, 2)
218+
ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0)
219+
ZEND_ARG_OBJ_INFO(0, value, V8\\Value, 0)
220+
ZEND_END_ARG_INFO()
221+
222+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_catch, ZEND_RETURN_VALUE, 2, V8\\PromiseObject, 0)
223+
ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0)
224+
ZEND_ARG_OBJ_INFO(0, handler, V8\\FunctionObject, 0)
225+
ZEND_END_ARG_INFO()
226+
227+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_then, ZEND_RETURN_VALUE, 2, V8\\PromiseObject, 0)
228+
ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0)
229+
ZEND_ARG_OBJ_INFO(0, handler, V8\\FunctionObject, 0)
230+
ZEND_END_ARG_INFO()
231+
232+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_hasHandler, ZEND_RETURN_VALUE, 0, _IS_BOOL, 0)
233+
ZEND_END_ARG_INFO()
234+
235+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_result, ZEND_RETURN_VALUE, 0, V8\\Value, 0)
236+
ZEND_END_ARG_INFO()
237+
238+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_state, ZEND_RETURN_VALUE, 0, IS_LONG, 0)
239+
ZEND_END_ARG_INFO()
240+
241+
242+
static const zend_function_entry php_v8_promise_methods[] = {
243+
PHP_V8_ME(Promise, __construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
244+
PHP_V8_ME(Promise, resolve, ZEND_ACC_PUBLIC)
245+
PHP_V8_ME(Promise, reject, ZEND_ACC_PUBLIC)
246+
PHP_V8_ME(Promise, catch, ZEND_ACC_PUBLIC)
247+
PHP_V8_ME(Promise, then, ZEND_ACC_PUBLIC)
248+
PHP_V8_ME(Promise, hasHandler, ZEND_ACC_PUBLIC)
249+
PHP_V8_ME(Promise, result, ZEND_ACC_PUBLIC)
250+
PHP_V8_ME(Promise, state, ZEND_ACC_PUBLIC)
251+
252+
PHP_FE_END
253+
};
254+
255+
256+
PHP_MINIT_FUNCTION(php_v8_promise) {
257+
zend_class_entry ce;
258+
INIT_NS_CLASS_ENTRY(ce, PHP_V8_NS, "PromiseObject", php_v8_promise_methods);
259+
this_ce = zend_register_internal_class_ex(&ce, php_v8_object_class_entry);
260+
261+
zend_declare_class_constant_long(this_ce, ZEND_STRL("STATE_PENDING"), static_cast<zend_long>(v8::Promise::PromiseState::kPending));
262+
zend_declare_class_constant_long(this_ce, ZEND_STRL("STATE_FULFILLED"), static_cast<zend_long>(v8::Promise::PromiseState::kFulfilled));
263+
zend_declare_class_constant_long(this_ce, ZEND_STRL("STATE_REJECTED"), static_cast<zend_long>(v8::Promise::PromiseState::kRejected));
264+
265+
return SUCCESS;
266+
}

0 commit comments

Comments
 (0)