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

Commit 04544df

Browse files
committed
Add Proxy and Promise builtin support, closes #55
1 parent 9299d64 commit 04544df

15 files changed

+1538
-1
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_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+
}

src/php_v8_promise.h

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
#ifndef PHP_V8_PROMISE_H
14+
#define PHP_V8_PROMISE_H
15+
16+
#include "php_v8_value.h"
17+
#include <v8.h>
18+
19+
extern "C" {
20+
#include "php.h"
21+
22+
#ifdef ZTS
23+
#include "TSRM.h"
24+
#endif
25+
}
26+
27+
extern zend_class_entry* php_v8_promise_class_entry;
28+
extern zend_class_entry* php_v8_promise_flags_class_entry;
29+
30+
31+
PHP_MINIT_FUNCTION(php_v8_promise);
32+
33+
#endif //PHP_V8_PROMISE_H

0 commit comments

Comments
 (0)