Skip to content

Commit

Permalink
feat: add DefineFunction & DefineProperty
Browse files Browse the repository at this point in the history
  • Loading branch information
LazuliKao committed Jul 28, 2023
1 parent c2d87f7 commit dbff056
Show file tree
Hide file tree
Showing 9 changed files with 543 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Loader/SetupContext.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using System.Runtime.InteropServices;
using Hosihikari.VanillaScript.QuickJS;
using Hosihikari.VanillaScript.QuickJS.Extensions;
using Hosihikari.VanillaScript.QuickJS.Types;

namespace Hosihikari.VanillaScript.Loader;

/// <summary>
/// add js module to JsContext
/// </summary>
internal static partial class Manager
{
//usage in js:
Expand All @@ -28,6 +32,7 @@ public static unsafe int JsModuleInitFunc(JsContext* ctx, JsModuleDef* module)
try
{
var instance = Native.JS_NewObject(ctx);
//instance.DefineFunction(ctx,"")
Native.JS_SetModuleExport(ctx, module, apiModuleName, instance);
}
catch (Exception e)
Expand Down
36 changes: 36 additions & 0 deletions src/QuickJS/Extensions/JsValueExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,40 @@ public static unsafe string ToString(this JsValue @this, JsContext* ctx)
{
return Native.JS_ToCStringLen2(ctx, @this);
}

public static unsafe bool DefineProperty(
this JsValue @this,
JsContext* ctx,
string propertyName,
JsValue value,
JsPropertyFlags flags = JsPropertyFlags.CWE
)
{
return Native.JS_DefinePropertyValueStr(ctx, @this, propertyName, value, flags);
}

//public static unsafe bool DefineProperty(
// this JsValue @this,
// JsContext* ctx,
// string propertyName,
// string value,
// JsPropertyFlags flags = JsPropertyFlags.CWE
//)
//{
// return Native.JS_DefinePropertyValueStr(ctx, @this, propertyName, value, flags);
//}
public static unsafe bool DefineFunction(
this JsValue @this,
JsContext* ctx,
string funcName,
delegate* unmanaged<JsContext*, JsValue, int, JsValue*, JsValue> func,
int argumentLength,
JscFunctionEnum cproto,
int magic = 0,
JsPropertyFlags flags = JsPropertyFlags.CWE
)
{
var value = Native.JS_NewCFunction2(ctx, func, funcName, argumentLength, cproto, magic);
return Native.JS_DefinePropertyValueStr(ctx, @this, funcName, value.Value, flags);
}
}
119 changes: 119 additions & 0 deletions src/QuickJS/Native.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.CompilerServices;
using System.Text.Json.Nodes;
using Hosihikari.NativeInterop;

Check failure on line 3 in src/QuickJS/Native.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'NativeInterop' does not exist in the namespace 'Hosihikari' (are you missing an assembly reference?)
using Hosihikari.NativeInterop.Utils;

Check failure on line 4 in src/QuickJS/Native.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'NativeInterop' does not exist in the namespace 'Hosihikari' (are you missing an assembly reference?)
using Hosihikari.VanillaScript.QuickJS.Exceptions;
Expand Down Expand Up @@ -221,4 +222,122 @@ private static void JS_FreeCString(JsContext* ctx, byte* ptr)

private static readonly Lazy<nint> _ptrJsFreeCString = GetPointerLazy("JS_FreeCString");
#endregion

#region JS_SetPropertyFunctionList
//ref #L36128
//todo

#endregion
#region JS_NewCFunction2
//JSValue JS_NewCFunction2(JSContext* ctx, JSCFunction* func,
// const char* name,
// int length, JSCFunctionEnum cproto, int magic)
//typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
public static SafeJsValue JS_NewCFunction2(
JsContext* ctx,
delegate* unmanaged<JsContext*, JsValue, int, JsValue*, JsValue> func,
string name,
int argumentLength, //Note: at least 'length' arguments will be readable in 'argv'
JscFunctionEnum cproto,
int magic
)
{
fixed (byte* ptr = StringUtils.StringToManagedUtf8(name))
{
var funcPtr = (delegate* unmanaged<
JsContext*,
delegate* unmanaged<JsContext*, JsValue, int, JsValue*, JsValue>,
byte*,
int,
JscFunctionEnum,
int,
JsValue>)
_ptrJsNewCFunction2.Value;
var result = funcPtr(ctx, func, ptr, argumentLength, cproto, magic);
if (result.IsException())
{
throw new QuickJsException(JS_GetException(ctx));
}
return new SafeJsValue(result, ctx);
}
}

private static readonly Lazy<nint> _ptrJsNewCFunction2 = GetPointerLazy("JS_NewCFunction2");
#endregion
#region JS_NewCFunction3
//
//todo JS_NewCFunction3 has protoVal which filled with ctx->function_proto in JS_NewCFunction2
///*
// static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
// const char *name,
// int length, JSCFunctionEnum cproto, int magic,
// JSValueConst proto_val)
// */
////typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
//public static JsValue JS_NewCFunction3(
// JsContext* ctx,
// delegate* unmanaged<JsContext*, JsValue, int, JsValue*, JsValue> func,
// string name,
// int length, //Note: at least 'length' arguments will be readable in 'argv'
// JscFunctionEnum cproto,
// int magic,
// JsValue protoVal
//)
//{

//}

#endregion
#region JS_GetClassProto
//JSValue JS_GetClassProto(JSContext* ctx, JSClassID class_id)
//{
// JSRuntime* rt = ctx->rt;
// assert(class_id < rt->class_count);
// return JS_DupValue(ctx, ctx->class_proto[class_id]);
//}
public static SafeJsValue JS_GetClassProto(JsContext* ctx, JsClassIdEnum classId)
{
var func = (delegate* unmanaged<JsContext*, JsClassIdEnum, JsValue>)
_ptrJsGetClassProto.Value;
var result = func(ctx, classId);
if (result.IsException())
{
throw new QuickJsException(JS_GetException(ctx));
}
//it use JS_DupValue so need to free
return new SafeJsValue(result, ctx);
}

private static readonly Lazy<nint> _ptrJsGetClassProto = GetPointerLazy("JS_GetClassProto");
#endregion

#region JS_DefinePropertyValueStr
//int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
// const char *prop, JSValue val, int flags)

public static bool JS_DefinePropertyValueStr(
JsContext* ctx,
JsValue thisObj,
string prop,
JsValue val,
JsPropertyFlags flags
)
{
fixed (byte* ptr = StringUtils.StringToManagedUtf8(prop))
{
var func = (delegate* unmanaged<JsContext*, JsValue, byte*, JsValue, int, int>)
_ptrJsDefinePropertyValueStr.Value;
var result = func(ctx, thisObj, ptr, val, (int)flags);
if (result == -1)
{
throw new QuickJsException(JS_GetException(ctx));
}
return result != 0;
}
}

private static readonly Lazy<nint> _ptrJsDefinePropertyValueStr = GetPointerLazy(
"JS_DefinePropertyValueStr"
);
#endregion
}
19 changes: 19 additions & 0 deletions src/QuickJS/Types/JsCFunctionEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Hosihikari.VanillaScript.QuickJS.Types;

/* C function definition */
public enum JscFunctionEnum
{
Generic,
GenericMagic,
Constructor,
ConstructorMagic,
ConstructorOrFunc,
ConstructorOrFuncMagic,
F_F,
F_F_F,
Getter,
Setter,
GetterMagic,
SetterMagic,
IteratorNext,
}
107 changes: 107 additions & 0 deletions src/QuickJS/Types/JsCFunctionListEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Runtime.InteropServices;

namespace Hosihikari.VanillaScript.QuickJS.Types;

//ref #L965

//typedef struct JSCFunctionListEntry
[StructLayout(LayoutKind.Sequential)]
internal unsafe ref struct JsCFunctionListEntry
{
// const char* name;
public byte* Name;

// uint8_t prop_flags;
public byte PropFlags;

// uint8_t def_type;
[MarshalAs(UnmanagedType.U1)]
public byte DefType;

// int16_t magic;
public short Magic;
public CFunctionListEntryUnion U;

[StructLayout(LayoutKind.Explicit)]
public ref struct CFunctionListEntryUnion
{
// union {
public ref struct Func
{
// struct {
// uint8_t length; /* XXX: should move outside union */
public byte length;

// uint8_t cproto; /* XXX: should move outside union */
public byte cproto;

// JSCFunctionType cfunc;
public JsCFunctionType cfunc;
// } func;
}

[FieldOffset(0)]
public Func func;

public ref struct GetSet
{
// struct {
// JSCFunctionType get;
public JsCFunctionType get;

// JSCFunctionType set;
public JsCFunctionType set;
// } getset;
}

[FieldOffset(0)]
public GetSet getset;

public ref struct Alias
{
// struct {
// const char* name;
public byte* name;

// int base;
public int @base;
// } alias;
}

[FieldOffset(0)]
public Alias alias;

public ref struct PropList
{
// struct {
// const struct JSCFunctionListEntry *tab;
public JsCFunctionListEntry* tab;

// int len;
public int len;
// } prop_list;
}

[FieldOffset(0)]
public PropList prop_list;

// const char* str;
// int32_t i32;
// int64_t i64;
// double f64;

[FieldOffset(0)]
public nint str;

[FieldOffset(0)]
public int i32;

[FieldOffset(0)]
public long i64;

[FieldOffset(0)]
public double f64;
// } u;
}
}
36 changes: 36 additions & 0 deletions src/QuickJS/Types/JsCFunctionType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Hosihikari.VanillaScript.QuickJS.Types
{
//ref #L925
[StructLayout(LayoutKind.Explicit)]
public ref struct JsCFunctionType
{
[FieldOffset(0)]
public unsafe void* func;

[FieldOffset(0)]
public double fvalue;
}

//typedef union JSCFunctionType {
// JSCFunction* generic;
// JSValue(*generic_magic)(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic);
// JSCFunction* constructor;
// JSValue(*constructor_magic)(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv, int magic);
// JSCFunction* constructor_or_func;
// double (* f_f) (double);
// double (* f_f_f) (double, double);
// JSValue(*getter)(JSContext* ctx, JSValueConst this_val);
// JSValue(*setter)(JSContext* ctx, JSValueConst this_val, JSValueConst val);
// JSValue(*getter_magic)(JSContext* ctx, JSValueConst this_val, int magic);
// JSValue(*setter_magic)(JSContext* ctx, JSValueConst this_val, JSValueConst val, int magic);
// JSValue(*iterator_next)(JSContext* ctx, JSValueConst this_val,
// int argc, JSValueConst* argv, int* pdone, int magic);
//} JSCFunctionType;
}
Loading

0 comments on commit dbff056

Please sign in to comment.