Skip to content

Commit

Permalink
fix: fix clr exception stack format in js
Browse files Browse the repository at this point in the history
  • Loading branch information
LazuliKao committed Aug 5, 2023
1 parent fc57653 commit f23efd4
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 91 deletions.
4 changes: 2 additions & 2 deletions src/Hook/JsLog/JsLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ static unsafe (string file, int line) GetJsSourceInfo(JsContext* ctx)
{
Native.JS_ThrowInternalError(ctx, "");
using var error = Native.JS_GetException(ctx);
var stack = error.Value.GetStringProperty(ctx, "stack");
var stack = error.Value.GetStringProperty(ctx, JsAtom.BuildIn.Stack);
// at trace (native)
// at <anonymous> (test.js:3)
var lineStr = stack.Split('\n')[1]; //at <anonymous> (test.js:3)
Expand Down Expand Up @@ -218,7 +218,7 @@ static unsafe string ParseLog(JsContext* ctx, ReadOnlySpan<JsValue> argv)
if (arg.Tag == JsTag.Object && Native.JS_IsError(ctx, arg))
{
sb.AppendLine();
sb.AppendLine(arg.GetStringProperty(ctx, "stack"));
sb.AppendLine(arg.GetStringProperty(ctx, JsAtom.BuildIn.Stack));
}
else
{
Expand Down
53 changes: 50 additions & 3 deletions src/QuickJS/Extensions/JsValueExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,22 @@ string propertyName
)
{
using var val = Native.JS_GetPropertyStr(ctx, @this, propertyName);
return Native.JS_ToCString(ctx, val.Value);
return val.ToString();
}

public static unsafe string GetStringProperty(this JsValue @this, JsContext* ctx, JsAtom atom)
{
using var val = Native.JS_GetPropertyInternal(ctx, @this, atom);
return val.ToString();
}

public static unsafe AutoDropJsValue GetProperty(
this JsValue @this,
JsContext* ctx,
JsAtom atom
)
{
return Native.JS_GetPropertyInternal(ctx, @this, atom);
}

public static unsafe AutoDropJsValue GetProperty(
Expand All @@ -131,6 +146,17 @@ string propertyName
return Native.JS_GetPropertyStr(ctx, @this, propertyName);
}

public static unsafe bool HasProperty(this JsValue @this, JsContext* ctx, JsAtom atom)
{
return Native.JS_HasProperty(ctx, @this, atom);
}

public static unsafe bool HasProperty(this JsValue @this, JsContext* ctx, string propertyName)
{
using var atom = Native.JS_NewAtom(ctx, propertyName);
return HasProperty(@this, ctx, atom.Value);
}

//JS_ToString
public static unsafe string ToString(this JsValue @this, JsContext* ctx)
{
Expand All @@ -143,12 +169,33 @@ public static unsafe string ToString(this JsValue @this, JsContextWrapper ctx) =
public static unsafe bool SetProperty(
this JsValue @this,
JsContext* ctx,
JsValue propertyName,
JsValue propertyKey,
JsValue value,
JsPropertyFlags flags = JsPropertyFlags.CWE
)
{
return Native.JS_SetPropertyValue(ctx, @this, propertyKey, value, flags);
}

public static unsafe bool SetProperty(
this JsValue @this,
JsContext* ctx,
string propertyName,
JsValue value
)
{
return Native.JS_SetPropertyStr(ctx, @this, propertyName, value);
}

public static unsafe bool SetProperty(
this JsValue @this,
JsContext* ctx,
JsAtom atom,
JsValue value,
JsPropertyFlags flags = JsPropertyFlags.CWE
)
{
return Native.JS_SetPropertyValue(ctx, @this, propertyName, value, flags);
return Native.JS_SetPropertyInternal(ctx, @this, atom, value, flags);
}

public static unsafe bool DefineProperty(
Expand Down
139 changes: 134 additions & 5 deletions src/QuickJS/Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,30 @@ public static void JS_SetConstructorBit(JsContext* ctx, JsValue @this, bool val)
);
#endregion

#region JS_GetPropertyInternal
//JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,JSAtom prop, JSValueConst receiver,JS_BOOL throw_ref_error);
public static AutoDropJsValue JS_GetPropertyInternal(
JsContext* ctx,
JsValue obj,
JsAtom prop,
bool throwRefError = false
)
{
var result = (
(delegate* unmanaged<JsContext*, JsValue, JsAtom, JsValue, byte, JsValue>)
_ptrJsGetPropertyInternal.Value
)(ctx, obj, prop, obj, throwRefError ? (byte)1 : (byte)0);
if (result.IsException())
{
ThrowPendingException(ctx);
}
return new AutoDropJsValue(result, ctx);
}

private static readonly Lazy<nint> _ptrJsGetPropertyInternal = GetPointerLazy(
"JS_GetPropertyInternal"
);
#endregion
#region JS_GetPropertyStr
public static AutoDropJsValue JS_GetPropertyStr(
JsContext* ctx,
Expand Down Expand Up @@ -336,6 +360,32 @@ JsPropertyFlags flags
"JS_DefinePropertyValue"
);
#endregion

#region JS_SetPropertyInternal

//int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,JSAtom prop, JSValue val, int flags)
public static bool JS_SetPropertyInternal(
JsContext* ctx,
JsValue thisObj,
JsAtom prop,
JsValue val,
JsPropertyFlags flags = JsPropertyFlags.Throw
)
{
var func = (delegate* unmanaged<JsContext*, JsValue, JsAtom, JsValue, int, int>)
_ptrJsSetPropertyInternal.Value;
var result = func(ctx, thisObj, prop, val, (int)flags);
if (result == -1)
{
ThrowPendingException(ctx);
}
return result == 1;
}

private static readonly Lazy<nint> _ptrJsSetPropertyInternal = GetPointerLazy(
"JS_SetPropertyInternal"
);
#endregion
#region JS_DefinePropertyValueStr
//int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
// const char *prop, JSValue val, int flags)
Expand Down Expand Up @@ -680,30 +730,89 @@ public static AutoDropJsValue JS_Invoke(
//private static readonly Lazy<nint> _ptrJsThrowError = GetPointerLazy("JS_ThrowError2");
//#endregion

#region JS_HasProperty

//int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
public static bool JS_HasProperty(JsContext* ctx, JsValue obj, JsAtom prop)
{
var func = (delegate* unmanaged<JsContext*, JsValue, JsAtom, int>)_ptrJsHasProperty.Value;
var result = func(ctx, obj, prop);
if (result == -1)
ThrowPendingException(ctx);
return result != 0;
}

private static readonly Lazy<nint> _ptrJsHasProperty = GetPointerLazy("JS_HasProperty");

#endregion
#region JS_Throw
//JSValue JS_Throw(JSContext *ctx, JSValue obj)
public static JsValue JS_Throw(JsContext* ctx, JsValue obj)
{
var func = (delegate* unmanaged<JsContext*, JsValue, JsValue>)_ptrJsThrow.Value;
var result = func(ctx, obj);
if (!result.IsException())
{
Log.Logger.Error("throw error may failed");
}
return result;
}

private static readonly Lazy<nint> _ptrJsThrow = GetPointerLazy("JS_Throw");

#endregion
#region JS_ThrowInternalError
//JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);

public static JsValue JS_ThrowInternalError(JsContext* ctx, Exception exception)
{
return JS_ThrowInternalError(ctx, exception.ToString());
return JS_ThrowInternalError(ctx, exception.Message, exception.StackTrace);
}

public static JsValue JS_ThrowInternalError(JsContext* ctx, string message)
public static JsValue JS_ThrowInternalError(
JsContext* ctx,
string message,
string? stack = null
)
{
var func = (delegate* unmanaged<JsContext*, byte*, JsValue>)_ptrJsThrowInternalError.Value;
var func = (delegate* unmanaged<JsContext*, byte*, byte*, JsValue>)
_ptrJsThrowInternalError.Value;
fixed (
byte* format = StringUtils.StringToManagedUtf8(
"%s" /* prevent format*/
)
)
fixed (
byte* ptr = StringUtils.StringToManagedUtf8(
message.Replace("%%", "%") /* prevent format*/
message /* prevent format*/
)
)
{
var result = func(ctx, ptr);
var result = func(ctx, format, ptr);
if (!result.IsException())
{
//it seem always return exception type
//so if not exception, it means throw failed ?
Log.Logger.Error("throw error may failed");
}
#if true// get thrown exception and append clr stack after js
if (!string.IsNullOrWhiteSpace(stack))
{
var error = JS_GetException(ctx); //get error object just throw
if (error.HasProperty(JsAtom.BuildIn.Stack))
{
var jsStack = error.GetStringProperty(JsAtom.BuildIn.Stack);
//append clr stack
jsStack += string.Join(
Environment.NewLine,
from line in stack.Split(Environment.NewLine)
select " " + line.TrimStart()
);
error.SetProperty(JsAtom.BuildIn.Stack, JS_NewString(ctx, jsStack).Steal());
}
JS_Throw(ctx, error.Value); //rethrow processed error
}
#endif
return result;
}
}
Expand Down Expand Up @@ -935,6 +1044,26 @@ public static AutoDropJsValue JS_GetPropertyUint32(JsContext* ctx, JsValue thisO

#endregion

#region JS_SetPropertyStr

//int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,const char* prop, JSValue val)
public static bool JS_SetPropertyStr(JsContext* ctx, JsValue thisObj, string prop, JsValue val)
{
var func = (delegate* unmanaged<JsContext*, JsValue, byte*, JsValue, int>)
_ptrJsSetPropertyStr.Value;
fixed (byte* p = StringUtils.StringToManagedUtf8(prop))
{
var result = func(ctx, thisObj, p, val);
if (result == -1)
ThrowPendingException(ctx);
return result != 0;
}
}

private static readonly Lazy<nint> _ptrJsSetPropertyStr = GetPointerLazy("JS_SetPropertyStr");

#endregion

#region JS_SetPropertyValue
// int JS_SetPropertyValue(JSContext* ctx, JSValueConst this_obj,JSValue prop, JSValue val, int flags)
public static bool JS_SetPropertyValue(
Expand Down
34 changes: 34 additions & 0 deletions src/QuickJS/Wrapper/AutoDropJsValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ public string GetStringProperty(string propertyName)
}
}

public string GetStringProperty(JsAtom atom)
{
unsafe
{
return _value.GetStringProperty(_context, atom);
}
}

public override string ToString()
{
unsafe
Expand Down Expand Up @@ -163,4 +171,30 @@ public unsafe void DefineFunction(
using var value = ctx.NewJsFunction(funcName, argumentLength, func, protoType);
_value.DefineProperty(ctx.Context, funcName, value.Steal(), propFlags);
}

public unsafe bool HasProperty(JsAtom atom)
{
return _value.HasProperty(_context, atom);
}

public unsafe bool HasProperty(string propertyName)
{
return _value.HasProperty(_context, propertyName);
}

public void SetProperty(JsAtom atom, JsValue value)
{
unsafe
{
_value.SetProperty(_context, atom, value);
}
}

public void SetProperty(string propertyName, JsValue value)
{
unsafe
{
_value.SetProperty(_context, propertyName, value);
}
}
}
Loading

0 comments on commit f23efd4

Please sign in to comment.