Skip to content
Draft
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
62 changes: 62 additions & 0 deletions ClearScript/V8/FastProxy/Uint8Array.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Microsoft.ClearScript.V8.SplitProxy
{
/// <summary>
/// Wraps a Uint8Array, an array of <see cref="byte"/>.
/// </summary>
public readonly ref struct Uint8Array
{
private readonly V8Object.Handle handle;

internal Uint8Array(V8Object.Handle pArray)
{
handle = pArray;

Length = (int)V8SplitProxyNative.InvokeRaw(static (instance, hObject) =>
{
V8Value.Ptr pArrayBuffer = instance.V8Value_New();
instance.V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out _, out _, out ulong length);
instance.V8Value_Delete(pArrayBuffer);
return length;
}, pArray);
}

/// <summary>
/// Copy the contents of the wrapped Uint8Array to a managed <see cref="byte"/> array.
/// </summary>
/// <param name="array">The destination array. It must be large enough to contain the entire
/// contents of the wrapped Uint8Array.</param>
public unsafe void CopyTo(byte[] array)
{
if (Length > array.Length)
throw new IndexOutOfRangeException(
$"Tried to copy {Length} items to a {array.Length} item array");

Action<IntPtr, (byte[] array, int length)> action = static (data, arg) =>
Marshal.Copy(data, arg.array, 0, arg.length);

var ctx = (action, (array, Length));
var pCtx = (IntPtr)Unsafe.AsPointer(ref ctx);

Action<IntPtr, IntPtr> actionWithArg = static (pData, pCtx) =>
{
ref var ctx = ref Unsafe.AsRef<(Action<IntPtr, (byte[], int)> action, (byte[], int) arg)>(pCtx.ToPointer());
ctx.action(pData, ctx.arg);
};

using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(actionWithArg))
{
var pAction = actionScope.Value;
V8SplitProxyNative.InvokeRaw(static (instance, ctx) => instance.V8Object_InvokeWithArrayBufferOrViewDataWithArg(ctx.handle, ctx.pAction, ctx.pCtx), (handle, pAction, pCtx));
}
}

/// <summary>
/// The length of the wrapped Uint8Array.
/// </summary>
public int Length { get; }
}
}
11 changes: 11 additions & 0 deletions ClearScript/V8/FastProxy/V8FastArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,17 @@ internal V8FastArgs(V8ScriptEngine engine, in ReadOnlySpan<V8Value.FastArg> args
/// </remarks>
public BigInteger GetBigInteger(int index, string name = null) => V8FastArgImpl.GetBigInteger(args[index], GetObject(index), argKind, name);

/// <summary>
/// Gets the <c><see cref="Uint8Array"/></c> value of the argument at the specified index.
/// </summary>
/// <param name="index">The argument index.</param>
/// <param name="name">An optional argument or property name.</param>
/// <returns>The <c><see cref="Uint8Array"/></c> value of the argument at the specified index.</returns>
/// <remarks>
/// This method throws an exception if the operation fails.
/// </remarks>
public Uint8Array GetUint8Array(int index, string name = null) => V8FastArgImpl.GetUint8Array(args[index], GetObject(index), argKind, name);

/// <summary>
/// Gets a nullable value of the given underlying type from the argument at the specified index.
/// </summary>
Expand Down