diff --git a/ClearScript/V8/FastProxy/Uint8Array.cs b/ClearScript/V8/FastProxy/Uint8Array.cs new file mode 100644 index 00000000..da2a6721 --- /dev/null +++ b/ClearScript/V8/FastProxy/Uint8Array.cs @@ -0,0 +1,62 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + /// + /// Wraps a Uint8Array, an array of . + /// + 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); + } + + /// + /// Copy the contents of the wrapped Uint8Array to a managed array. + /// + /// The destination array. It must be large enough to contain the entire + /// contents of the wrapped Uint8Array. + 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 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 actionWithArg = static (pData, pCtx) => + { + ref var ctx = ref Unsafe.AsRef<(Action 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)); + } + } + + /// + /// The length of the wrapped Uint8Array. + /// + public int Length { get; } + } +} diff --git a/ClearScript/V8/FastProxy/V8FastArgs.cs b/ClearScript/V8/FastProxy/V8FastArgs.cs index 0f500439..e30e76f2 100644 --- a/ClearScript/V8/FastProxy/V8FastArgs.cs +++ b/ClearScript/V8/FastProxy/V8FastArgs.cs @@ -408,6 +408,17 @@ internal V8FastArgs(V8ScriptEngine engine, in ReadOnlySpan args /// public BigInteger GetBigInteger(int index, string name = null) => V8FastArgImpl.GetBigInteger(args[index], GetObject(index), argKind, name); + /// + /// Gets the value of the argument at the specified index. + /// + /// The argument index. + /// An optional argument or property name. + /// The value of the argument at the specified index. + /// + /// This method throws an exception if the operation fails. + /// + public Uint8Array GetUint8Array(int index, string name = null) => V8FastArgImpl.GetUint8Array(args[index], GetObject(index), argKind, name); + /// /// Gets a nullable value of the given underlying type from the argument at the specified index. ///