예제 #1
0
        public ITypedArray CastNativeArray(object managedArray)
        {
            var         arrayType = managedArray.GetType();
            ITypedArray array;

            // Here are listed some JavaScript array types:
            // https://github.com/mono/mono/blob/a7f5952c69ae76015ccaefd4dfa8be2274498a21/sdks/wasm/bindings-test.cs
            if (arrayType == typeof(byte[]))
            {
                array = Uint8Array.From((byte[])managedArray);
            }
            else if (arrayType == typeof(float[]))
            {
                array = Float32Array.From((float[])managedArray);
            }
            else if (arrayType == typeof(ushort[]))
            {
                array = Uint16Array.From((ushort[])managedArray);
            }
            else
            {
                throw new NotImplementedException();
            }

            return(array);
        }
예제 #2
0
 public Blob(byte[] Data) :
     this(((System.Func <JSObject>)(() =>
 {
     var Uint8AR = Uint8Array.From(Data);
     return(new JSObject(Runtime.New("Blob", new Array(Uint8AR), new { type = "application/octet-stream" }), true));
 }))())
 { }
예제 #3
0
        private static async void RunFunctionTaskResult()
        {
            var result = await((Uint8Array)Runtime.GetGlobalObject("MNData")).ToArray().
                         Deserialize <Func <Task <object> > >()();

            WebWorker.CurrentWebWorker.PostMessage(Uint8Array.From(result.Serialize()));
        }
예제 #4
0
        public static IEnumerable <object[]> ArrayType_TestData()
        {
            _objectPrototype ??= new Function("return Object.prototype.toString;");
            yield return(new object[] { _objectPrototype.Call(), "Uint8Array", Uint8Array.From(new byte[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Array", new Array(10) });
        }
예제 #5
0
 public void TexSubImage2D(
     uint target,
     int level,
     int xoffset,
     int yoffset,
     int width,
     int height,
     uint format,
     uint type,
     ReadOnlySpan <byte> source)
 {
     using (var nativeArray = Uint8Array.From(source))
     {
         TexSubImage2D(
             target,
             level,
             xoffset,
             yoffset,
             width,
             height,
             format,
             type,
             nativeArray);
     }
 }
예제 #6
0
        private static void SetTypedArrayByte(JSObject obj)
        {
            var dragons = "hic sunt dracones";

            byte[] buffer = System.Text.Encoding.ASCII.GetBytes(dragons);
            obj.SetObjectProperty("dracones", Uint8Array.From(buffer));
        }
예제 #7
0
        /// <summary>
        /// Send data on <see cref="T:WebAssembly.Net.WebSockets.ClientWebSocket"/> as an asynchronous operation.
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="buffer">Buffer.</param>
        /// <param name="messageType">Message type.</param>
        /// <param name="endOfMessage">If set to <c>true</c> end of message.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        public override async Task SendAsync(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
        {
            ThrowIfNotConnected();

            if (messageType != WebSocketMessageType.Binary &&
                messageType != WebSocketMessageType.Text)
            {
                throw new ArgumentException($"Invalid message type: '{messageType}' specified in method 'SendAsync'.  Valid types are 'Binary' and 'Text'",
                                            nameof(messageType));
            }

            if (!endOfMessage)
            {
                writeBuffer = writeBuffer ?? new MemoryStream();

                writeBuffer.Write(buffer.Array, buffer.Offset, buffer.Count);
                return;
            }
            else if (writeBuffer != null)
            {
                writeBuffer.Write(buffer.Array, buffer.Offset, buffer.Count);

                if (!writeBuffer.TryGetBuffer(out buffer))
                {
                    throw new WebSocketException(WebSocketError.NativeError);
                }
            }

            var tcsSend = new TaskCompletionSource <bool> ();
            // Wrap the cancellationToken in a using so that it can be disposed of whether
            // we successfully send or not.
            // Otherwise any timeout/cancellation would apply to the full session.
            var writtenBuffer = writeBuffer;

            writeBuffer = null;

            using (cancellationToken.Register(() => tcsSend.TrySetCanceled())) {
                try {
                    if (messageType == WebSocketMessageType.Binary)
                    {
                        using (var uint8Buffer = Uint8Array.From(buffer)){
                            innerWebSocket.Invoke("send", uint8Buffer);
                            tcsSend.SetResult(true);
                        }
                    }
                    else if (messageType == WebSocketMessageType.Text)
                    {
                        var strBuffer = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
                        innerWebSocket.Invoke("send", strBuffer);
                        tcsSend.SetResult(true);
                    }
                } catch (Exception excb) {
                    tcsSend.TrySetException(new WebSocketException(WebSocketError.NativeError, excb));
                } finally {
                    writtenBuffer?.Dispose();
                }
                await tcsSend.Task;
            }
        }
예제 #8
0
 public void Send(ArraySegment <byte> buffer)
 {
     ThrowIfNotConnected();
     using (var uint8Buffer = Uint8Array.From(buffer))
     {
         hostObject.Invoke("send", uint8Buffer);
     }
 }
예제 #9
0
        public static void Uint8ArrayFrom(Function objectPrototype)
        {
            var        array = new byte[50];
            Uint8Array from  = Uint8Array.From(array);

            Assert.Equal(50, from.Length);
            Assert.Equal("[object Uint8Array]", objectPrototype.Call(from));
        }
예제 #10
0
        public async Task <object> Run(Func <Task <object> > Func)
        {
            await IsReady;

            Worker.PostMessage("MNData", Uint8Array.From(Func.Serialize()));
            var Message = Worker.GetMessage();
            await Worker.Run($"self.MN.RunFunctionTaskResult()");

            return((await Message).GetData <Uint8Array>().ToArray().Deserialize <object>());
        }
예제 #11
0
        public async Task Run(Func <Task> Action)
        {
            await IsReady;

            Worker.PostMessage("MNData", Uint8Array.From(Action.Serialize()));
            var Message = Worker.GetMessage();
            await Worker.Run($"self.MN.RunFunctionTask()");

            await Message;
        }
예제 #12
0
        // Called by the AOT profiler to save profile data into Module.aot_profile_data
        internal unsafe static void DumpAotProfileData(ref byte buf, int len, string s)
        {
            var arr = new byte [len];

            fixed(void *p = &buf)
            {
                var span = new ReadOnlySpan <byte> (p, len);

                // Send it to JS
                var js_dump = (JSObject)Runtime.GetGlobalObject("Module");

                js_dump.SetObjectProperty("aot_profile_data", Uint8Array.From(span));
            }
        }
예제 #13
0
        /// <summary>
        /// Send data on <see cref="T:WebAssembly.Net.WebSockets.ClientWebSocket"/> as an asynchronous operation.
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="buffer">Buffer.</param>
        /// <param name="messageType">Message type.</param>
        /// <param name="endOfMessage">If set to <c>true</c> end of message.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        public override async Task SendAsync(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
        {
            // TODO: Support send async buffering.

            ThrowIfNotConnected();

            if (messageType != WebSocketMessageType.Binary &&
                messageType != WebSocketMessageType.Text)
            {
                throw new ArgumentException($"Invalid message type: '{messageType}' specified in method 'SendAsync'.  Valid types are 'Binary' and 'Text'",
                                            nameof(messageType));
            }

            var tcsSend = new TaskCompletionSource <bool> ();

            // Wrap the cancellationToken in a using so that it can be disposed of whether
            // we successfully send or not.
            // Otherwise any timeout/cancellation would apply to the full session.
            using (cancellationToken.Register(() => tcsSend.TrySetCanceled())) {
                if (messageType == WebSocketMessageType.Binary)
                {
                    try {
                        using (var uint8Buffer = Uint8Array.From(buffer))
                        {
                            innerWebSocket.Invoke("send", uint8Buffer);
                            tcsSend.SetResult(true);
                        }
                    } catch (Exception excb) {
                        throw new WebSocketException(WebSocketError.NativeError, excb);
                    }
                    await tcsSend.Task;
                }
                if (messageType == WebSocketMessageType.Text)
                {
                    try {
                        var bytesToSend = new byte [buffer.Count];
                        Buffer.BlockCopy(buffer.Array, buffer.Offset, bytesToSend, 0, buffer.Count);

                        var strBuffer = Encoding.UTF8.GetString(bytesToSend, 0, bytesToSend.Length);
                        innerWebSocket.Invoke("send", strBuffer);
                        tcsSend.SetResult(true);
                    } catch (Exception exct) {
                        throw new WebSocketException(WebSocketError.NativeError, exct);
                    }

                    await tcsSend.Task;
                }
            }
        }
예제 #14
0
        public async Task <object> Run(Func <Task <object> > Func)
        {
            await IsReady;

            Worker.PostMessage("MNData", Uint8Array.From(Func.Serialize()));
            var Message = Worker.GetMessage();
            await Worker.Run($"self.MN.RunFunctionTaskResult()");

            var Result = (await Message).GetData <Uint8Array>().ToArray();

            if (Result.Length == 0)
            {
                throw new Exception("Error On Proccess");
            }
            return(Result.Deserialize <object>());
        }
예제 #15
0
 public void TexImage2D(
     uint target,
     int level,
     int internalformat,
     int width,
     int height,
     int border,
     uint format,
     uint type,
     ReadOnlySpan <byte> source)
 {
     using (var nativeArray = Uint8Array.From(source))
     {
         TexImage2D(target, level, internalformat, width, height, border, format, type, nativeArray);
     }
 }
예제 #16
0
    public unsafe static void Dump(ref byte buf, int len, string s)
    {
        var arr = new byte [len];

        fixed(void *p = &buf)
        {
            var span = new ReadOnlySpan <byte> (p, len);

            // Send it to JS
            try {
                var js_dump = (JSObject)Runtime.GetGlobalObject("AotProfileData");
                js_dump.SetObjectProperty("data", Uint8Array.From(span));
            } catch (Exception ex) {
                Console.WriteLine(ex);
                Environment.Exit(1);
            }
        }
    }
예제 #17
0
        public static IEnumerable <object[]> ArrayType_TestData()
        {
            _objectPrototype ??= new Function("return Object.prototype.toString;");
            yield return(new object[] { _objectPrototype.Call(), "Uint8Array", Uint8Array.From(new byte[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Uint8ClampedArray", Uint8ClampedArray.From(new byte[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Int8Array", Int8Array.From(new sbyte[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Uint16Array", Uint16Array.From(new ushort[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Int16Array", Int16Array.From(new short[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Uint32Array", Uint32Array.From(new uint[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Int32Array", Int32Array.From(new int[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Float32Array", Float32Array.From(new float[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Float64Array", Float64Array.From(new double[10]) });

            yield return(new object[] { _objectPrototype.Call(), "Array", new Array(10) });
        }
예제 #18
0
        private async Task doFetch(TaskCompletionSource <HttpResponseMessage> tcs, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            try {
                var requestObject = new JSObject();
                requestObject.SetObjectProperty("method", request.Method.Method);

                // See https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials for
                // standard values and meanings
                requestObject.SetObjectProperty("credentials", DefaultCredentials);

                // See https://developer.mozilla.org/en-US/docs/Web/API/Request/cache for
                // standard values and meanings
                requestObject.SetObjectProperty("cache", Cache);

                // See https://developer.mozilla.org/en-US/docs/Web/API/Request/mode for
                // standard values and meanings
                requestObject.SetObjectProperty("mode", Mode);

                // We need to check for body content
                if (request.Content != null)
                {
                    if (request.Content is StringContent)
                    {
                        requestObject.SetObjectProperty("body", await request.Content.ReadAsStringAsync());
                    }
                    else
                    {
                        using (var uint8Buffer = Uint8Array.From(await request.Content.ReadAsByteArrayAsync()))
                        {
                            requestObject.SetObjectProperty("body", uint8Buffer);
                        }
                    }
                }

                // Process headers
                // Cors has it's own restrictions on headers.
                // https://developer.mozilla.org/en-US/docs/Web/API/Headers
                using (var jsHeaders = new HostObject("Headers")) {
                    if (request.Headers != null)
                    {
                        foreach (var header in request.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                jsHeaders.Invoke("append", header.Key, value);
                            }
                        }
                    }
                    if (request.Content?.Headers != null)
                    {
                        foreach (var header in request.Content.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                jsHeaders.Invoke("append", header.Key, value);
                            }
                        }
                    }
                    requestObject.SetObjectProperty("headers", jsHeaders);
                }

                JSObject           abortController    = null;
                JSObject           signal             = null;
                WasmHttpReadStream wasmHttpReadStream = null;

                CancellationTokenRegistration abortRegistration = default(CancellationTokenRegistration);
                if (cancellationToken.CanBeCanceled)
                {
                    abortController = new HostObject("AbortController");

                    signal = (JSObject)abortController.GetObjectProperty("signal");
                    requestObject.SetObjectProperty("signal", signal);
                    abortRegistration = cancellationToken.Register((Action)(() => {
                        if (abortController.JSHandle != -1)
                        {
                            abortController.Invoke((string)"abort");
                            abortController?.Dispose();
                        }
                        wasmHttpReadStream?.Dispose();
                    }));
                }

                var args = new Core.Array();
                args.Push(request.RequestUri.ToString());
                args.Push(requestObject);

                requestObject.Dispose();

                var response = (Task <object>)fetch.Invoke("apply", window, args);
                args.Dispose();

                var t = await response;

                var status = new WasmFetchResponse((JSObject)t, abortController, abortRegistration);

                //Console.WriteLine($"bodyUsed: {status.IsBodyUsed}");
                //Console.WriteLine($"ok: {status.IsOK}");
                //Console.WriteLine($"redirected: {status.IsRedirected}");
                //Console.WriteLine($"status: {status.Status}");
                //Console.WriteLine($"statusText: {status.StatusText}");
                //Console.WriteLine($"type: {status.ResponseType}");
                //Console.WriteLine($"url: {status.Url}");

                HttpResponseMessage httpresponse = new HttpResponseMessage((HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), status.Status.ToString()));

                httpresponse.Content = StreamingSupported && StreamingEnabled
                                    ? new StreamContent(wasmHttpReadStream = new WasmHttpReadStream(status))
                                    : (HttpContent) new WasmHttpContent(status);

                // Fill the response headers
                // CORS will only allow access to certain headers.
                // If a request is made for a resource on another origin which returns the CORs headers, then the type is cors.
                // cors and basic responses are almost identical except that a cors response restricts the headers you can view to
                // `Cache-Control`, `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and `Pragma`.
                // View more information https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types
                //
                // Note: Some of the headers may not even be valid header types in .NET thus we use TryAddWithoutValidation
                using (var respHeaders = (JSObject)status.Headers) {
                    if (respHeaders != null)
                    {
                        using (var entriesIterator = (JSObject)respHeaders.Invoke("entries")) {
                            JSObject nextResult = null;
                            try {
                                nextResult = (JSObject)entriesIterator.Invoke("next");
                                while (!(bool)nextResult.GetObjectProperty("done"))
                                {
                                    using (var resultValue = (WebAssembly.Core.Array)nextResult.GetObjectProperty("value")) {
                                        var name  = (string)resultValue [0];
                                        var value = (string)resultValue [1];
                                        if (!httpresponse.Headers.TryAddWithoutValidation(name, value))
                                        {
                                            if (httpresponse.Content != null)
                                            {
                                                if (!httpresponse.Content.Headers.TryAddWithoutValidation(name, value))
                                                {
                                                    Console.WriteLine($"Warning: Can not add response header for name: {name} value: {value}");
                                                }
                                            }
                                        }
                                    }
                                    nextResult?.Dispose();
                                    nextResult = (JSObject)entriesIterator.Invoke("next");
                                }
                            } finally {
                                nextResult?.Dispose();
                            }
                        }
                    }
                }

                tcs.SetResult(httpresponse);

                signal?.Dispose();
            } catch (Exception exception) {
                tcs.SetException(exception);
            }
        }
예제 #19
0
        private async Task doFetch(TaskCompletionSource <HttpResponseMessage> tcs, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            try {
                var requestObject = new JSObject();
                requestObject.SetObjectProperty("method", request.Method.Method);

                // See https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials for
                // standard values and meanings
                requestObject.SetObjectProperty("credentials", DefaultCredentials);

                // See https://developer.mozilla.org/en-US/docs/Web/API/Request/cache for
                // standard values and meanings
                requestObject.SetObjectProperty("cache", Cache);

                // See https://developer.mozilla.org/en-US/docs/Web/API/Request/mode for
                // standard values and meanings
                requestObject.SetObjectProperty("mode", Mode);

                // We need to check for body content
                if (request.Content != null)
                {
                    if (request.Content is StringContent)
                    {
                        requestObject.SetObjectProperty("body", await request.Content.ReadAsStringAsync());
                    }
                    else
                    {
                        using (var uint8Buffer = Uint8Array.From(await request.Content.ReadAsByteArrayAsync()))
                        {
                            requestObject.SetObjectProperty("body", uint8Buffer);
                        }
                    }
                }

                // Process headers
                // Cors has it's own restrictions on headers.
                // https://developer.mozilla.org/en-US/docs/Web/API/Headers
                using (var jsHeaders = new HostObject("Headers")) {
                    if (request.Headers != null)
                    {
                        foreach (var header in request.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                jsHeaders.Invoke("append", header.Key, value);
                            }
                        }
                    }
                    if (request.Content?.Headers != null)
                    {
                        foreach (var header in request.Content.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                jsHeaders.Invoke("append", header.Key, value);
                            }
                        }
                    }
                    requestObject.SetObjectProperty("headers", jsHeaders);
                }

                JSObject           abortController    = null;
                JSObject           signal             = null;
                WasmHttpReadStream wasmHttpReadStream = null;

                CancellationTokenRegistration abortRegistration = default(CancellationTokenRegistration);
                if (cancellationToken.CanBeCanceled)
                {
                    abortController = new HostObject("AbortController");

                    signal = (JSObject)abortController.GetObjectProperty("signal");
                    requestObject.SetObjectProperty("signal", signal);
                    abortRegistration = cancellationToken.Register((Action)(() => {
                        if (abortController.JSHandle != -1)
                        {
                            abortController.Invoke((string)"abort");
                            abortController?.Dispose();
                        }
                        wasmHttpReadStream?.Dispose();
                    }));
                }

                var args = new Core.Array();
                args.Push(request.RequestUri.ToString());
                args.Push(requestObject);

                requestObject.Dispose();

                var response = (Task <object>)fetch.Invoke("apply", window, args);
                args.Dispose();

                var t = await response;

                var status = new WasmFetchResponse((JSObject)t, abortController, abortRegistration);

                //Console.WriteLine($"bodyUsed: {status.IsBodyUsed}");
                //Console.WriteLine($"ok: {status.IsOK}");
                //Console.WriteLine($"redirected: {status.IsRedirected}");
                //Console.WriteLine($"status: {status.Status}");
                //Console.WriteLine($"statusText: {status.StatusText}");
                //Console.WriteLine($"type: {status.ResponseType}");
                //Console.WriteLine($"url: {status.Url}");

                HttpResponseMessage httpresponse = new HttpResponseMessage((HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), status.Status.ToString()));

                httpresponse.Content = StreamingSupported && StreamingEnabled
                                    ? new StreamContent(wasmHttpReadStream = new WasmHttpReadStream(status))
                                    : (HttpContent) new WasmHttpContent(status);

                // Fill the response headers
                // CORS will only allow access to certain headers.
                // If a request is made for a resource on another origin which returns the CORs headers, then the type is cors.
                // cors and basic responses are almost identical except that a cors response restricts the headers you can view to
                // `Cache-Control`, `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and `Pragma`.
                // View more information https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types
                //
                // Note: Some of the headers may not even be valid header types in .NET thus we use TryAddWithoutValidation
                using (var respHeaders = status.Headers) {
                    // Here we invoke the forEach on the headers object
                    // Note: the Action takes 3 objects and not two.  The other seems to be the Header object.
                    var foreachAction = new Action <object, object, object> ((value, name, other) => {
                        if (!httpresponse.Headers.TryAddWithoutValidation((string)name, (string)value))
                        {
                            if (httpresponse.Content != null)
                            {
                                if (!httpresponse.Content.Headers.TryAddWithoutValidation((string)name, (string)value))
                                {
                                    Console.WriteLine($"Warning: Can not add response header for name: {name} value: {value}");
                                }
                            }
                        }
                        ((JSObject)other).Dispose();
                    });

                    try {
                        respHeaders.Invoke("forEach", foreachAction);
                    } finally {
                        // Do not remove the following line of code.  The httpresponse is used in the lambda above when parsing the Headers.
                        // if a local is captured (used) by a lambda it becomes heap memory as we translate them into fields on an object.
                        // The foreachAction is allocated when marshalled to JavaScript.  Since we do not know when JS is finished with the
                        // Action we need to tell the Runtime to de-allocate the object and remove the instance from JS as well.
                        WebAssembly.Runtime.FreeObject(foreachAction);
                    }
                }

                tcs.SetResult(httpresponse);

                signal?.Dispose();
            } catch (Exception exception) {
                tcs.SetException(exception);
            }
        }
예제 #20
0
        private async Task doFetch(TaskCompletionSource <HttpResponseMessage> tcs, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            try {
                var requestObject = new JSObject();

                if (request.Properties.TryGetValue("WebAssemblyFetchOptions", out var fetchOoptionsValue) &&
                    fetchOoptionsValue is IDictionary <string, object> fetchOptions)
                {
                    foreach (var item in fetchOptions)
                    {
                        requestObject.SetObjectProperty(item.Key, item.Value);
                    }
                }

                requestObject.SetObjectProperty("method", request.Method.Method);

                // We need to check for body content
                if (request.Content != null)
                {
                    if (request.Content is StringContent)
                    {
                        requestObject.SetObjectProperty("body", await request.Content.ReadAsStringAsync());
                    }
                    else
                    {
                        // 2.1.801 seems to have a problem with the line
                        // using (var uint8Buffer = Uint8Array.From(await request.Content.ReadAsByteArrayAsync ()))
                        // so we split it up into two lines.
                        var byteAsync = await request.Content.ReadAsByteArrayAsync();

                        using (var uint8Buffer = Uint8Array.From(byteAsync))
                        {
                            requestObject.SetObjectProperty("body", uint8Buffer);
                        }
                    }
                }

                // Process headers
                // Cors has it's own restrictions on headers.
                // https://developer.mozilla.org/en-US/docs/Web/API/Headers
                using (var jsHeaders = new HostObject("Headers")) {
                    if (request.Headers != null)
                    {
                        foreach (var header in request.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                jsHeaders.Invoke("append", header.Key, value);
                            }
                        }
                    }
                    if (request.Content?.Headers != null)
                    {
                        foreach (var header in request.Content.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                jsHeaders.Invoke("append", header.Key, value);
                            }
                        }
                    }
                    requestObject.SetObjectProperty("headers", jsHeaders);
                }

                WasmHttpReadStream wasmHttpReadStream = null;

                JSObject abortController = new HostObject("AbortController");
                JSObject signal          = (JSObject)abortController.GetObjectProperty("signal");
                requestObject.SetObjectProperty("signal", signal);
                signal.Dispose();

                CancellationTokenSource       abortCts          = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                CancellationTokenRegistration abortRegistration = abortCts.Token.Register((Action)(() => {
                    if (abortController.JSHandle != -1)
                    {
                        abortController.Invoke("abort");
                        abortController?.Dispose();
                    }
                    wasmHttpReadStream?.Dispose();
                }));

                var args = new Runtime.InteropServices.JavaScript.Array();
                args.Push(request.RequestUri.ToString());
                args.Push(requestObject);

                requestObject.Dispose();

                var response = fetch.Invoke("apply", window, args) as Task <object>;
                args.Dispose();
                if (response == null)
                {
                    throw new Exception("Internal error marshalling the response Promise from `fetch`.");
                }

                var t = await response;

                var status = new WasmFetchResponse((JSObject)t, abortController, abortCts, abortRegistration);

                //Console.WriteLine($"bodyUsed: {status.IsBodyUsed}");
                //Console.WriteLine($"ok: {status.IsOK}");
                //Console.WriteLine($"redirected: {status.IsRedirected}");
                //Console.WriteLine($"status: {status.Status}");
                //Console.WriteLine($"statusText: {status.StatusText}");
                //Console.WriteLine($"type: {status.ResponseType}");
                //Console.WriteLine($"url: {status.Url}");

                HttpResponseMessage httpresponse = new HttpResponseMessage((HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), status.Status.ToString()));

                var streamingEnabled = request.Properties.TryGetValue("WebAssemblyEnableStreamingResponse", out var streamingEnabledValue) && (bool)streamingEnabledValue;

                httpresponse.Content = StreamingSupported && streamingEnabled
                                        ? new StreamContent(wasmHttpReadStream = new WasmHttpReadStream(status))
                                        : (HttpContent) new WasmHttpContent(status);

                // Fill the response headers
                // CORS will only allow access to certain headers.
                // If a request is made for a resource on another origin which returns the CORs headers, then the type is cors.
                // cors and basic responses are almost identical except that a cors response restricts the headers you can view to
                // `Cache-Control`, `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and `Pragma`.
                // View more information https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types
                //
                // Note: Some of the headers may not even be valid header types in .NET thus we use TryAddWithoutValidation
                using (var respHeaders = (JSObject)status.Headers) {
                    if (respHeaders != null)
                    {
                        using (var entriesIterator = (JSObject)respHeaders.Invoke("entries")) {
                            JSObject nextResult = null;
                            try {
                                nextResult = (JSObject)entriesIterator.Invoke("next");
                                while (!(bool)nextResult.GetObjectProperty("done"))
                                {
                                    using (var resultValue = (Runtime.InteropServices.JavaScript.Array)nextResult.GetObjectProperty("value")) {
                                        var name  = (string)resultValue [0];
                                        var value = (string)resultValue [1];
                                        if (!httpresponse.Headers.TryAddWithoutValidation(name, value))
                                        {
                                            if (httpresponse.Content != null)
                                            {
                                                if (!httpresponse.Content.Headers.TryAddWithoutValidation(name, value))
                                                {
                                                    Console.WriteLine($"Warning: Can not add response header for name: {name} value: {value}");
                                                }
                                            }
                                        }
                                    }
                                    nextResult?.Dispose();
                                    nextResult = (JSObject)entriesIterator.Invoke("next");
                                }
                            } finally {
                                nextResult?.Dispose();
                            }
                        }
                    }
                }

                tcs.SetResult(httpresponse);
            } catch (JSException jsExc)  {
                var httpExc = new System.Net.Http.HttpRequestException(jsExc.Message);
                tcs.SetException(httpExc);
            } catch (Exception exception)  {
                tcs.SetException(exception);
            }
        }
예제 #21
0
        public static Uint8Array Uint8ArrayFrom()
        {
            var array = new byte[50];

            return(Uint8Array.From(array));
        }