PrintOptions(
            System.Collections.Generic.IEnumerable<System.Type> optionTypes)
        {
            var options = new Core.Array<Core.ICommandLineArgument>();
            foreach (var optType in optionTypes)
            {
                var arg = System.Activator.CreateInstance(optType) as Core.ICommandLineArgument;
                options.Add(arg);
            }

            foreach (var arg in options.OrderBy(key => key.LongName))
            {
                if (arg is Core.ICustomHelpText)
                {
                    Core.Log.Info("{0}: {1}", (arg as Core.ICustomHelpText).OptionHelp, arg.ContextHelp);
                }
                else
                {
                    if (null == arg.ShortName)
                    {
                        Core.Log.Info("{0}: {1}", arg.LongName, arg.ContextHelp);
                    }
                    else
                    {
                        Core.Log.Info("{0} (or {1}): {2}", arg.LongName, arg.ShortName, arg.ContextHelp);
                    }
                }
                Core.Log.Info("");
            }
        }
Exemple #2
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);
            }
        }
Exemple #3
0
        private async Task ConnectAsyncJavaScript(Uri uri, CancellationToken cancellationToken)
        {
            var tcsConnect = new TaskCompletionSource <bool> ();

            // For Abort/Dispose.  Calling Abort on the request at any point will close the connection.
            cts.Token.Register(AbortRequest);

            // Wrap the cancellationToken in a using so that it can be disposed of whether
            // we successfully connected or failed trying.
            // Otherwise any timeout/cancellation would apply to the full session.
            // In the failure case we need to release the references and dispose of the objects.
            using (cancellationToken.Register(() => tcsConnect.TrySetCanceled())) {
                try {
                    Core.Array subProtocols = null;
                    if (Options.RequestedSubProtocols.Count > 0)
                    {
                        subProtocols = new Core.Array();
                        foreach (var item in Options.RequestedSubProtocols)
                        {
                            subProtocols.Push(item);
                        }
                    }
                    innerWebSocket = new HostObject("WebSocket", uri.ToString(), subProtocols);

                    subProtocols?.Dispose();

                    // Setup the onError callback
                    onError = new Action <JSObject> ((errorEvt) => {
                        errorEvt.Dispose();
                    });

                    // Attach the onError callback
                    innerWebSocket.SetObjectProperty("onerror", onError);

                    // Setup the onClose callback
                    onClose = new Action <JSObject> ((closeEvt) => {
                        innerWebSocketCloseStatus            = (WebSocketCloseStatus)closeEvt.GetObjectProperty("code");
                        innerWebSocketCloseStatusDescription = closeEvt.GetObjectProperty("reason")?.ToString();
                        var mess = new ReceivePayload(WebSocketHelpers.EmptyPayload, WebSocketMessageType.Close);
                        receiveMessageQueue.BufferPayload(mess);

                        if (!tcsConnect.Task.IsCanceled && !tcsConnect.Task.IsCompleted && !tcsConnect.Task.IsFaulted)
                        {
                            tcsConnect.SetException(new WebSocketException(WebSocketError.NativeError));
                        }
                        else
                        {
                            tcsClose?.SetResult(true);
                        }

                        closeEvt.Dispose();
                    });

                    // Attach the onClose callback
                    innerWebSocket.SetObjectProperty("onclose", onClose);

                    // Setup the onOpen callback
                    onOpen = new Action <JSObject> ((evt) => {
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            // Change internal state to 'connected' to enable the other methods
                            if (Interlocked.CompareExchange(ref state, connected, connecting) != connecting)
                            {
                                // Aborted/Disposed during connect.
                                throw new ObjectDisposedException(GetType().FullName);
                            }

                            tcsConnect.SetResult(true);
                        }

                        evt.Dispose();
                    });

                    // Attach the onOpen callback
                    innerWebSocket.SetObjectProperty("onopen", onOpen);

                    // Setup the onMessage callback
                    onMessage = new Action <JSObject> ((messageEvent) => {
                        ThrowIfNotConnected();

                        // get the events "data"
                        var eventData = messageEvent.GetObjectProperty("data");

                        // If the messageEvent's data property is marshalled as a JSObject then we are dealing with
                        // binary data
                        if (eventData is JSObject)
                        {
                            // TODO: Handle ArrayBuffer binary type but have only seen 'blob' so far without
                            // changing the default websocket binary type manually.
                            if (innerWebSocket.GetObjectProperty("binaryType").ToString() == "blob")
                            {
                                Action <JSObject> loadend = null;
                                // Create a new "FileReader" object
                                using (var reader = new HostObject("FileReader")) {
                                    loadend = new Action <JSObject> ((loadEvent) => {
                                        using (var target = (JSObject)loadEvent.GetObjectProperty("target")) {
                                            if ((int)target.GetObjectProperty("readyState") == 2)
                                            {
                                                using (var binResult = (ArrayBuffer)target.GetObjectProperty("result")) {
                                                    var mess = new ReceivePayload(binResult, WebSocketMessageType.Binary);
                                                    receiveMessageQueue.BufferPayload(mess);
                                                    Runtime.FreeObject(loadend);
                                                }
                                            }
                                        }
                                        loadEvent.Dispose();
                                    });

                                    reader.Invoke("addEventListener", "loadend", loadend);

                                    using (var blobData = (JSObject)messageEvent.GetObjectProperty("data"))
                                        reader.Invoke("readAsArrayBuffer", blobData);
                                }
                            }
                            else
                            {
                                throw new NotImplementedException($"WebSocket bynary type '{innerWebSocket.GetObjectProperty ("binaryType").ToString ()}' not supported.");
                            }
                        }
                        else if (eventData is string)
                        {
                            var mess = new ReceivePayload(Encoding.UTF8.GetBytes(((string)eventData).ToString()), WebSocketMessageType.Text);
                            receiveMessageQueue.BufferPayload(mess);
                        }
                        messageEvent.Dispose();
                    });

                    // Attach the onMessage callaback
                    innerWebSocket.SetObjectProperty("onmessage", onMessage);

                    await tcsConnect.Task;
                } catch (Exception wse) {
                    ConnectExceptionCleanup();
                    WebSocketException wex = new WebSocketException("WebSocket connection failure.", wse);
                    throw wex;
                }
            }
        }
        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);
            }
        }
Exemple #5
0
        Main(
            string[] args)
        {
#if false
            // take control of Ctrl+C
            System.Console.CancelKeyPress += new System.ConsoleCancelEventHandler(HandleCancellation);
#endif

            try
            {
                var totalTimeProfile = new Core.TimeProfile(Core.ETimingProfiles.TimedTotal);
                var processCommandLineProfile = new Core.TimeProfile(Core.ETimingProfiles.ProcessCommandLine);

                totalTimeProfile.StartProfile();
                processCommandLineProfile.StartProfile();

                var verbosityLevel = (Core.EVerboseLevel)Core.CommandLineProcessor.Evaluate(new Core.Options.VerbosityLevel());
                switch (verbosityLevel)
                {
                    case Core.EVerboseLevel.None:
                    case Core.EVerboseLevel.Info:
                    case Core.EVerboseLevel.Detail:
                    case Core.EVerboseLevel.Full:
                        Core.Graph.Instance.VerbosityLevel = verbosityLevel;
                        break;

                    default:
                        throw new Core.Exception("Unrecognized verbosity level, {0}", verbosityLevel);
                }

                if (Core.CommandLineProcessor.Evaluate(new Core.Options.PrintHelp()))
                {
                    CommandLineArgumentHelper.PrintHelp();
                    return;
                }

                if (Core.CommandLineProcessor.Evaluate(new Core.Options.PrintVersion()))
                {
                    CommandLineArgumentHelper.PrintVersion();
                    return;
                }

                if (Core.CommandLineProcessor.Evaluate(new Core.Options.CreateDebugProject()))
                {
                    DebugProject.Create();
                    return;
                }

                if (Core.CommandLineProcessor.Evaluate(new Core.Options.MakePackage()))
                {
                    Core.PackageUtilities.MakePackage();
                    return;
                }

                if (Core.CommandLineProcessor.Evaluate(new Core.Options.AddDependentPackage()))
                {
                    Core.PackageUtilities.AddDependentPackage();
                    return;
                }

                if (Core.CommandLineProcessor.Evaluate(new Core.Options.ShowDefinitionFile()))
                {
                    Core.PackageUtilities.IdentifyAllPackages(allowDuplicates: true, enforceBamAssemblyVersions: false);
                    Core.Graph.Instance.MasterPackage.Show();
                    return;
                }

                // configure
                Core.Graph.Instance.BuildRoot = Core.CommandLineProcessor.Evaluate(new Core.Options.BuildRoot());
                Core.Graph.Instance.Mode = Core.CommandLineProcessor.Evaluate(new Core.Options.BuildMode());
                if (null == Core.Graph.Instance.Mode)
                {
                    throw new Core.Exception("No build mode specified");
                }

                var configs = new Core.Array<Core.Environment>();
                var requestedConfigs = Core.CommandLineProcessor.Evaluate(new Core.Options.BuildConfigurations());
                if (0 == requestedConfigs.Count)
                {
                    // default
                    requestedConfigs.Add(new Core.StringArray("debug"));
                }
                foreach (var configOption in requestedConfigs)
                {
                    foreach (var config in configOption)
                    {
                        var env = new Core.Environment();
                        env.Configuration = Core.Configuration.FromString(config);
                        configs.Add(env);
                    }
                }

                processCommandLineProfile.StopProfile();

                Core.EntryPoint.Execute(configs);

                totalTimeProfile.StopProfile();
            }
            catch (Core.Exception exception)
            {
                Core.Exception.DisplayException(exception);
                System.Environment.ExitCode = -1;
            }
            catch (System.Exception exception)
            {
                var message = new System.Text.StringBuilder();
                message.AppendFormat("{0} not handled: {1}", exception.GetType().ToString(), exception.Message);
                message.AppendLine();
                message.AppendLine(exception.StackTrace);
                Core.Log.ErrorMessage(message.ToString());
                System.Environment.ExitCode = -2;
            }
            finally
            {
                if (Core.Graph.Instance.BuildEnvironments.Count > 0)
                {
                    Core.Log.Info((0 == System.Environment.ExitCode) ? "\nBuild Succeeded" : "\nBuild Failed");

                    if (Core.CommandLineProcessor.Evaluate(new Core.Options.PrintStatistics()))
                    {
                        Core.Statistics.Display();
                    }

                    Core.Log.DebugMessage("Exit code {0}", System.Environment.ExitCode);
                }
            }
        }