Skip to content

Commit

Permalink
feat: add api to use js Promise
Browse files Browse the repository at this point in the history
  • Loading branch information
LazuliKao committed Jul 30, 2023
1 parent 5cacf68 commit d61c061
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
12 changes: 10 additions & 2 deletions src/QuickJS/Helper/JsValueCreateHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ public static JsValue NewFloat64(double d)
/// </summary>
/// <param name="ctx"></param>
/// <param name="str"></param>
/// <param name="autoDrop"> whether to decrease ref count when pass to unmanaged environment </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe AutoDropJsValue NewString(JsContext* ctx, string str)
{
Expand All @@ -204,7 +203,6 @@ public static unsafe AutoDropJsValue NewString(JsContext* ctx, string str)
/// </summary>
/// <param name="ctx"></param>
/// <param name="str"></param>
/// <param name="autoDrop"> whether to decrease ref count when pass to unmanaged environment </param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe AutoDropJsValue FromJson(JsContext* ctx, string str)
Expand All @@ -222,4 +220,14 @@ public static unsafe AutoDropJsValue NewObject(JsContext* ctx)
{
return Native.JS_NewObject(ctx);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe AutoDropJsValue NewPromise(
JsContext* ctx,
out SafeJsValue resolve,
out SafeJsValue reject
)
{
return Native.JS_NewPromiseCapability(ctx, out resolve, out reject);
}
}
67 changes: 66 additions & 1 deletion src/QuickJS/Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,6 @@ public static string JS_GetScriptOrModuleName(JsContext* ctx, int nStackLevels)
"JS_GetScriptOrModuleName"
);
#endregion

#region JS_AtomToCString

//const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)
Expand All @@ -658,4 +657,70 @@ public static void JS_FreeAtom(JsContext* ctx, JsAtom v)
private static readonly Lazy<nint> _ptrJsFreeAtom = GetPointerLazy("JS_FreeAtom");

#endregion
#region JS_NewPromiseCapability
//JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs)
//ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
public static AutoDropJsValue JS_NewPromiseCapability(
JsContext* ctx,
out SafeJsValue resolve,
out SafeJsValue reject
)
{
//#L46698
/*
for(i = 0; i < 2; i++)
resolving_funcs[i] = JS_DupValue(ctx, s->data[i]);
*/
var resolvingFunc = stackalloc JsValue[2];
var func = (delegate* unmanaged<JsContext*, JsValue*, JsValue>)
_ptrJsNewPromiseCapability.Value;
var result = func(ctx, resolvingFunc);
if (result.IsException())
ThrowPendingException(ctx);
resolve = new SafeJsValue(new AutoDropJsValue(resolvingFunc[0], ctx));
reject = new SafeJsValue(new AutoDropJsValue(resolvingFunc[1], ctx));
return new AutoDropJsValue(result, ctx);
}

private static readonly Lazy<nint> _ptrJsNewPromiseCapability = GetPointerLazy(
"JS_NewPromiseCapability"
);
#endregion

#region JS_Call
/*
JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
int argc, JSValueConst *argv)
{
return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
}
static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
int argc, JSValueConst *argv)
{
JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
JS_FreeValue(ctx, func_obj);
return res;
}
*/
public static AutoDropJsValue JS_Call(
JsContext* ctx,
JsValue func,
JsValue thisObj,
int argc,
JsValue* argv
)
{
var funcPtr = (delegate* unmanaged<JsContext*, JsValue, JsValue, int, JsValue*, JsValue>)
_ptrJsCall.Value;
var result = funcPtr(ctx, func, thisObj, argc, argv);
if (result.IsException())
ThrowPendingException(ctx);
return new AutoDropJsValue(result, ctx);
}

private static readonly Lazy<nint> _ptrJsCall = GetPointerLazy("JS_Call");
#endregion
}
8 changes: 8 additions & 0 deletions src/QuickJS/Wrapper/SafeJsValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ public class SafeJsValue
private JsValue _value;
private unsafe JsContext* _ctx;

public SafeJsValue(JsValue value)
{
_value = value;
_value.UnsafeAddRefCount();
}

public SafeJsValue(AutoDropJsValue value)
{
//steal the value to prevent free, then the value will be memory safe in managed environment
Expand All @@ -23,6 +29,8 @@ public SafeJsValue(AutoDropJsValue value)
~SafeJsValue()
{
//remove ref count to free the value
//this was originally done by AutoDropJsValue.Dispose()
//but we steal the value from AutoDropJsValue, so we need to free it manually here
unsafe
{
_value.UnsafeRemoveRefCount(_ctx);
Expand Down

0 comments on commit d61c061

Please sign in to comment.