add function channel

This commit is contained in:
ekibun
2020-08-15 14:52:53 +08:00
parent 2731f97c63
commit 7b35868c5c
12 changed files with 313 additions and 52 deletions

View File

@@ -3,16 +3,17 @@
* @Author: ekibun
* @Date: 2020-08-07 13:55:52
* @LastEditors: ekibun
* @LastEditTime: 2020-08-13 13:47:16
* @LastEditTime: 2020-08-15 14:45:00
*/
#pragma once
#include "quickjspp/quickjspp.hpp"
#include "quickjspp/quickjs/list.h"
#include <future>
#include <string.h>
namespace qjs
{
#include "quickjspp/quickjs/list.h"
static JSClassID js_dart_promise_class_id;
typedef struct
@@ -22,11 +23,12 @@ namespace qjs
} JSOSFutureArgv;
using JSFutureReturn = std::function<JSOSFutureArgv(JSContext *)>;
using DartChannel = std::function<std::future<JSFutureReturn>(std::string, std::string)>;
using DartChannel = std::function<std::promise<JSFutureReturn> *(std::string, Value)>;
typedef struct
{
struct list_head link;
std::promise<JSFutureReturn> *promise;
std::shared_future<JSFutureReturn> future;
JSValue resolve;
JSValue reject;
@@ -35,10 +37,10 @@ namespace qjs
typedef struct JSThreadState
{
struct list_head os_future; /* list of JSOSFuture.link */
std::function<std::future<JSFutureReturn>(std::string, std::string)> channel;
DartChannel channel;
} JSThreadState;
static JSValue js_add_future(Value resolve, Value reject, std::shared_future<JSFutureReturn> future)
static JSValue js_add_future(Value resolve, Value reject, std::promise<JSFutureReturn> *promise)
{
JSRuntime *rt = JS_GetRuntime(resolve.ctx);
JSThreadState *ts = (JSThreadState *)JS_GetRuntimeOpaque(rt);
@@ -61,7 +63,8 @@ namespace qjs
JS_FreeValue(resolve.ctx, obj);
return JS_EXCEPTION;
}
th->future = future;
th->promise = promise;
th->future = promise->get_future();
th->resolve = JS_DupValue(resolve.ctx, jsResolve);
th->reject = JS_DupValue(reject.ctx, jsReject);
list_add_tail(&th->link, &ts->os_future);
@@ -69,7 +72,7 @@ namespace qjs
return obj;
}
JSValue js_dart_future(Value resolve, Value reject, std::string name, std::string args)
JSValue js_dart_future(Value resolve, Value reject, std::string name, Value args)
{
JSRuntime *rt = JS_GetRuntime(resolve.ctx);
JSThreadState *ts = (JSThreadState *)JS_GetRuntimeOpaque(rt);
@@ -116,6 +119,7 @@ namespace qjs
{
JSOSFuture *th = list_entry(el, JSOSFuture, link);
th->future.get();
delete th->promise;
unlink_future(rt, th);
free_future(rt, th);
}
@@ -159,7 +163,6 @@ namespace qjs
{
JSOSFutureArgv argv = th->future.get()(ctx);
JSValue resolve, reject;
int64_t delay;
/* the timer expired */
resolve = th->resolve;
th->resolve = JS_UNDEFINED;

View File

@@ -3,7 +3,7 @@
* @Author: ekibun
* @Date: 2020-08-08 10:30:59
* @LastEditors: ekibun
* @LastEditTime: 2020-08-13 13:47:28
* @LastEditTime: 2020-08-15 13:13:43
*/
#pragma once
@@ -21,8 +21,7 @@ namespace qjs
{
struct EngineTask
{
std::string command;
std::string name;
std::function<Value(Context&)> invoke;
std::function<void(std::string)> resolve;
std::function<void(std::string)> reject;
};
@@ -72,10 +71,26 @@ namespace qjs
R"xxx(
import * as __DartImpl from "__DartImpl";
globalThis.dart = (method, ...args) => new Promise((res, rej) =>
__DartImpl.__invoke((v) => res(JSON.parse(v)), rej, method, JSON.stringify(args)));
__DartImpl.__invoke(res, rej, method, args));
)xxx",
"<dart>", JS_EVAL_TYPE_MODULE);
std::vector<EngineTaskResolver> unresolvedTask;
Value promiseWrapper = ctx.eval(
R"xxx(
(value) => {
const __ret = Promise.resolve(value)
.then(v => {
__ret.__value = v;
__ret.__resolved = true;
}).catch(e => {
__ret.__error = e;
__ret.__rejected = true;
});
return __ret;
}
)xxx",
"<PromiseWrapper>", JS_EVAL_TYPE_GLOBAL);
// 循环
while (!this->stoped)
{
@@ -93,25 +108,11 @@ namespace qjs
if (task.resolve)
try
{
ctx.global()["__evalstr"] = JS_NewString(ctx.ctx, task.command.c_str());
Value ret = ctx.eval(
R"xxx(
(() => {
const __ret = Promise.resolve(eval(__evalstr))
.then(v => {
__ret.__value = v;
__ret.__resolved = true;
}).catch(e => {
__ret.__error = e;
__ret.__rejected = true;
});
return __ret;
})()
)xxx",
task.name.c_str());
Value val = task.invoke(ctx);
Value ret = Value{ctx.ctx, JS_Call(ctx.ctx, promiseWrapper.v, ctx.global().v, 1, &(val.v))};
unresolvedTask.emplace_back(EngineTaskResolver{ret, std::move(task.resolve), std::move(task.reject)});
}
catch (exception e)
catch (exception)
{
task.reject(getStackTrack(ctx.getException()));
}
@@ -152,16 +153,16 @@ namespace qjs
{
idle = js_dart_poll(ctx.ctx);
}
catch (exception e)
catch (exception)
{
handleException(ctx.getException());
}
// 空闲时reject所有task
if (idle && !JS_IsJobPending(rt.rt) && !unresolvedTask.empty())
{
for (EngineTaskResolver &task : unresolvedTask)
for (EngineTaskResolver &_task : unresolvedTask)
{
task.reject("Promise cannot resolve");
_task.reject("Promise cannot resolve");
}
unresolvedTask.clear();
}