/// <summary>
        /// Parse a <see cref="DebugServerException"/> from the server response.
        /// </summary>
        /// <param name="content">
        /// JSON response returned by the debug server.
        /// </param>
        /// <returns>The exception instance.</returns>
        public static DebugServerException Parse(string content)
        {
            if (!string.IsNullOrEmpty(content))
            {
                try
                {
                    var jsonObject  = JObject.Parse(content);
                    var fileName    = jsonObject.Value <string>("filename");
                    var description = jsonObject.Value <string>("description");
                    if (description != null)
                    {
                        return(new DebugServerException(
                                   jsonObject.Value <string>("description"),
                                   ShortenFileName(fileName),
                                   jsonObject.Value <int>("lineNumber"),
                                   jsonObject.Value <int>("column")));
                    }
                }
                catch (JsonException ex)
                {
                    RnLog.Error(ReactConstants.RNW, ex, $"Failure deserializing debug server exception message.");
                }
            }

            return(null);
        }
        private async Task <ReactContext> InitializeReactContextAsync(
            Func <IJavaScriptExecutor> jsExecutorFactory,
            JavaScriptBundleLoader jsBundleLoader,
            CancellationToken token)
        {
            var currentReactContext = _currentReactContext;

            if (currentReactContext != null)
            {
                await TearDownReactContextAsync(currentReactContext, token);

                _currentReactContext = null;
            }

            try
            {
                var reactContext = await CreateReactContextCoreAsync(jsExecutorFactory, jsBundleLoader, token);
                await SetupReactContextAsync(reactContext);

                return(reactContext);
            }
            catch (OperationCanceledException)
                when(token.IsCancellationRequested)
                {
                    RnLog.Info(ReactConstants.RNW, $"ReactInstanceManager: Creating React context has been canceled");
                    throw;
                }
            catch (Exception ex)
            {
                RnLog.Error(ReactConstants.RNW, ex, $"ReactInstanceManager: Exception when creating React context: {ex.Message}");
                _devSupportManager.HandleException(ex);
            }

            return(null);
        }
        /// <summary>
        /// Runs the script at the given path.
        /// </summary>
        /// <param name="sourcePath">The source path.</param>
        /// <param name="sourceUrl">The source URL.</param>
        public void RunScript(string sourcePath, string sourceUrl)
        {
            if (sourcePath == null)
            {
                throw new ArgumentNullException(nameof(sourcePath));
            }
            if (sourceUrl == null)
            {
                throw new ArgumentNullException(nameof(sourceUrl));
            }

            var startupCode = default(string);

            if (IsUnbundle(sourcePath))
            {
                _unbundle = new FileBasedJavaScriptUnbundle(sourcePath);
                InstallNativeRequire();
                startupCode = _unbundle.GetStartupCode();
            }
            else if (IsIndexedUnbundle(sourcePath))
            {
                _unbundle = new IndexedJavaScriptUnbundle(sourcePath);
                InstallNativeRequire();
                startupCode = _unbundle.GetStartupCode();
            }
            else
            {
                startupCode = LoadScript(sourcePath);

                try
                {
                    if (this._modifyBundle != null)
                    {
                        //Modify bundle function returns modified bundle.
                        var updatedBundle = this._modifyBundle(startupCode);
                        startupCode = updatedBundle;
                    }
                }
                catch (Exception ex)
                {
                    RnLog.Error("Native", ex, @"Exception during bundle modification.");
#if DEBUG
                    throw;
#endif
                }
            }

            EvaluateScript(startupCode, sourceUrl);
        }
        private JavaScriptValue NativeLoggingHook(
            JavaScriptValue callee,
            bool isConstructCall,
            JavaScriptValue[] arguments,
            ushort argumentCount,
            IntPtr callbackData)
        {
            try
            {
                var message  = arguments[1].ToString();
                var logLevel = (LogLevel)(int)arguments[2].ToDouble();
                RnLog.Info("JS", $"{logLevel} {message}");
            }
            catch
            {
                RnLog.Error("JS", $"Unable to process JavaScript console statement");
            }

            return(JavaScriptValue.Undefined);
        }
        public void close(ushort code, string reason, int id)
        {
            if (!_webSocketConnections.TryGetValue(id, out var webSocket))
            {
                RnLog.Warn(ReactConstants.RNW, $"Cannot close WebSocket. Unknown WebSocket id {id}.");

                return;
            }

            try
            {
                var writer = _dataWriters[id];
                _dataWriters.Remove(id);
                _webSocketConnections.Remove(id);
                writer.Dispose();
                webSocket.Close(code, reason);
            }
            catch (Exception ex)
            {
                RnLog.Error(ReactConstants.RNW, ex, $"Could not close WebSocket connection for id '{id}'.");
            }
        }
Exemplo n.º 6
0
        public /* TODO: internal? */ void InvokeFunction(string module, string method, JArray arguments, string tracingName)
        {
            QueueConfiguration.JavaScriptQueue.Dispatch(() =>
            {
                QueueConfiguration.JavaScriptQueue.AssertOnThread();

                if (IsDisposed)
                {
                    return;
                }

                using (Tracer.Trace(Tracer.TRACE_TAG_REACT_BRIDGE, tracingName).Start())
                {
                    if (_bridge == null)
                    {
                        RnLog.Error(ReactConstants.RNW, $"Invoking JS callback before bridge has been initialized. tracingName:{tracingName}.");
                        throw new InvalidOperationException($"Bridge has not been initialized. tracingName:{tracingName}.");
                    }

                    _bridge.CallFunction(module, method, arguments);
                }
            });
        }
        private static void JsExecutorOnNewLogLine(ChakraBridge.LogLevel logLevel, string logline)
        {
            // ChakraBridge.LogLevel value is lost when it gets marshaled to .Net native optimized code,
            // we need to do a proper marshaling to get actual value
            // Also, JavaScript already has a log level in the message, hence just RnLog.Info
            string            tag     = "JS";
            FormattableString message = $"{logline}";

            switch (logLevel)
            {
            case ChakraBridge.LogLevel.Error:
                RnLog.Error(tag, message);
                break;

            case ChakraBridge.LogLevel.Warning:
                RnLog.Warn(tag, message);
                break;

            case ChakraBridge.LogLevel.Info:
            case ChakraBridge.LogLevel.Trace:
                RnLog.Info(tag, message);
                break;
            }
        }
        /// <summary>
        /// Runs the JavaScript at the given path.
        /// </summary>
        /// <param name="sourcePath">The source path.</param>
        /// <param name="sourceUrl">The source URL.</param>
        public void RunScript(string sourcePath, string sourceUrl)
        {
            if (sourcePath == null)
            {
                throw new ArgumentNullException(nameof(sourcePath));
            }
            if (sourceUrl == null)
            {
                throw new ArgumentNullException(nameof(sourceUrl));
            }

            try
            {
                var binPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, BytecodeFileName);

                if (_useSerialization)
                {
                    var srcFileInfo = new FileInfo(sourcePath);
                    var binFileInfo = new FileInfo(binPath);

                    bool ranSuccessfully = false;
                    // The idea is to run the JS bundle and generate bytecode for it on a background thread.
                    // This eliminates the need to delay the first start when the app doesn't have bytecode.
                    // Next time the app starts, it checks if bytecode is still good and  runs it directly.
                    if (binFileInfo.Exists && binFileInfo.LastWriteTime > srcFileInfo.LastWriteTime)
                    {
                        try
                        {
                            Native.ThrowIfError((JavaScriptErrorCode)_executor.RunSerializedScript(sourcePath, binPath, sourceUrl));
                            ranSuccessfully = true;
                        }
                        catch (JavaScriptUsageException exc)
                        {
                            if (exc.ErrorCode == JavaScriptErrorCode.BadSerializedScript)
                            {
                                // Bytecode format is dependent on Chakra engine version, so an OS upgrade may require a recompilation
                                RnLog.Warn(ReactConstants.RNW, $"Serialized bytecode script is corrupted or wrong format, will generate new one");
                            }
                            else
                            {
                                // Some more severe error. We still have a chance (recompiling), so we keep continuing.
                                RnLog.Error(ReactConstants.RNW, exc, $"Failed to run serialized bytecode script, will generate new one");
                            }

                            File.Delete(binPath);
                        }
                    }
                    else
                    {
                        RnLog.Info(ReactConstants.RNW, $"Serialized bytecode script doesn't exist or is obsolete, will generate one");
                    }

                    if (!ranSuccessfully)
                    {
                        Task.Run(() =>
                        {
                            try
                            {
                                // In Chakra JS engine, only one runtime can be active on a particular thread at a time,
                                // and a runtime can only be active on one thread at a time. However it's possible to
                                // create two runtimes and let them run on different threads.
                                var rt = new ChakraBridge.NativeJavaScriptExecutor();

                                Native.ThrowIfError((JavaScriptErrorCode)rt.InitializeHost());
                                Native.ThrowIfError((JavaScriptErrorCode)rt.SerializeScript(sourcePath, binPath));
                                Native.ThrowIfError((JavaScriptErrorCode)rt.DisposeHost());
                            }
                            catch (Exception ex)
                            {
                                RnLog.Error(ReactConstants.RNW, ex, $"Failed to generate serialized bytecode script.");
                                // It's fine if the bytecode couldn't be generated: RN can still use the JS bundle.
                            }
                        });

                        Native.ThrowIfError((JavaScriptErrorCode)_executor.RunScript(sourcePath, sourceUrl));
                    }
                }
                else
                {
                    Native.ThrowIfError((JavaScriptErrorCode)_executor.RunScript(sourcePath, sourceUrl));
                }
            }
            catch (JavaScriptScriptException ex)
            {
                var jsonError  = JavaScriptValueToJTokenConverter.Convert(ex.Error);
                var message    = jsonError.Value <string>("message");
                var stackTrace = jsonError.Value <string>("stack");
                throw new Modules.Core.JavaScriptException(message ?? ex.Message, stackTrace, ex);
            }
        }