Skip to content

more promise support #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions include/quickjs-msvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1016,11 +1016,16 @@ JSValue JS_SetDelete(JSContext *ctx, JSValueConst this_val,

void JS_SetClear(JSContext *ctx, JSValueConst this_val);
JSValue JS_DupModule(JSContext *ctx, JSModuleDef* v);

/*-------end fuctions for v8 api---------*/
JSValue JS_GET_MODULE_NS(JSContext *ctx, JSModuleDef* v);
int JS_ReleaseLoadedModule(JSContext *ctx, const char* path);

JSValue JS_GetPromiseResult(JSContext *ctx, JSValue promise);
int JS_GetPromiseState(JSValue promise);
bool JS_FullfillOrRejectPromise(JSContext *ctx, JSValueConst promise,
JSValueConst value, int is_reject);
int JS_IsPromise(JSValue promise);
/*-------end fuctions for v8 api---------*/

#undef js_unlikely
#undef js_force_inline

Expand Down
26 changes: 26 additions & 0 deletions include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ class V8_EXPORT Value {

bool IsUint32() const;

bool IsPromise() const;

V8_WARN_UNUSED_RESULT MaybeLocal<BigInt> ToBigInt(
Local<Context> context) const;

Expand Down Expand Up @@ -742,11 +744,35 @@ class V8_EXPORT ArrayBufferView : public Object {

class V8_EXPORT Promise : public Object {
public:
enum PromiseState { kPending, kFulfilled, kRejected };

V8_INLINE static Promise* Cast(class Value* obj) {
return static_cast<Promise*>(obj);
}

Isolate* GetIsolate();

class V8_EXPORT Resolver : public Object {
public:

/**
* Create a new resolver, along with an associated promise in pending state.
*/
static V8_WARN_UNUSED_RESULT MaybeLocal<Resolver> New(
Local<Context> context);

Local<Promise> GetPromise();

V8_WARN_UNUSED_RESULT Maybe<bool> Resolve(Local<Context> context,
Local<Value> value);

V8_WARN_UNUSED_RESULT Maybe<bool> Reject(Local<Context> context,
Local<Value> value);
};

Local<Value> Result();

PromiseState State();
};

enum {
Expand Down
35 changes: 31 additions & 4 deletions quickjs/quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -54158,9 +54158,6 @@ JSValue JS_DupModule(JSContext *ctx, JSModuleDef* v)
{
return JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, v));
}

/*-------end fuctions for v8 api---------*/

JSValue JS_GET_MODULE_NS(JSContext *ctx, JSModuleDef* v)
{
return js_get_module_ns(ctx, v);
Expand All @@ -54186,4 +54183,34 @@ int JS_ReleaseLoadedModule(JSContext *ctx, const char* path)
}
JS_FreeAtom(ctx, name);
return 0;
}
}
JSValue JS_GetPromiseResult(JSContext *ctx, JSValue promise)
{
JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
switch (s->promise_state)
{
case JS_PROMISE_PENDING:
return JS_Undefined();
default:
return JS_DupValue(ctx, s->promise_result);
}
}
int JS_GetPromiseState(JSValue promise)
{
JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
return (int)s->promise_state;
}
int JS_IsPromise(JSValue promise)
{
JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
return (int)(s != NULL);
}
int JS_FullfillOrRejectPromise(JSContext *ctx, JSValueConst promise,
JSValueConst value, int is_reject)
{
if (JS_GetPromiseState(promise) != 0) //pending
return 0;
fulfill_or_reject_promise(ctx, promise, value, is_reject);
return 1;
}
/*-------end fuctions for v8 api---------*/
50 changes: 49 additions & 1 deletion src/v8-impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,51 @@ Isolate* Promise::GetIsolate() {
return Isolate::current_;
}

Local<Value> Promise::Result() {
JSValue result = JS_GetPromiseResult(GetIsolate()->GetCurrentContext()->context_, value_);

Value* val = GetIsolate()->Alloc<Value>();
val->value_ = result;
return Local<Value>(val);
}

Promise::PromiseState Promise::State() {
int promiseStateInQuickJS = JS_GetPromiseState(value_);
switch(promiseStateInQuickJS) {
case 0:
return Promise::PromiseState::kPending;
case 1:
return Promise::PromiseState::kFulfilled;
case 2:
return Promise::PromiseState::kRejected;
}
}

MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
auto Isolate = context->GetIsolate();
Promise::Resolver *resolver = Isolate->Alloc<Promise::Resolver>();

JSValue resolving_funcs[2];
auto ctx = Isolate->current_context_->context_;
resolver->value_ = JS_NewPromiseCapability(ctx, resolving_funcs);
JS_FreeValue(ctx, resolving_funcs[0]);
JS_FreeValue(ctx, resolving_funcs[1]);

return MaybeLocal<Promise::Resolver>(Local<Promise::Resolver>(resolver));
}

Local<Promise> Promise::Resolver::GetPromise() {
return Local<Promise>(Promise::Cast(this));
}

Maybe<bool> Promise::Resolver::Resolve(Local<Context> context, Local<Value> value) {
return Maybe<bool>(JS_FullfillOrRejectPromise(context->context_, value_, value->value_, 0));
}

Maybe<bool> Promise::Resolver::Reject(Local<Context> context, Local<Value> value) {
return Maybe<bool>(JS_FullfillOrRejectPromise(context->context_, value_, value->value_, 1));
}

void V8FinalizerWrap(JSRuntime *rt, JSValue val) {
Isolate* isolate = (Isolate*)JS_GetRuntimeOpaque(rt);
Isolate::Scope Isolatescope(isolate);
Expand Down Expand Up @@ -333,6 +378,10 @@ bool Value::IsUint32() const{
return (bool)JS_IsNumber(value_);
}

bool Value::IsPromise() const{
return (bool)JS_IsPromise(value_);
}

MaybeLocal<BigInt> Value::ToBigInt(Local<Context> context) const {
if (IsBigInt()) {
return MaybeLocal<BigInt>(Local<BigInt>(static_cast<BigInt*>(const_cast<Value*>(this))));
Expand Down Expand Up @@ -428,7 +477,6 @@ int String::Utf8Length(Isolate* isolate) const {
int String::WriteUtf8(Isolate* isolate, char* buffer) const {
size_t len;
const char* p = JS_ToCStringLen(isolate->current_context_->context_, &len, value_);

memcpy(buffer, p, len);

JS_FreeCString(isolate->current_context_->context_, p);
Expand Down