public void close(ushort code, string reason, int id) { Websockets.Net.IWebSocketConnection webSocket; if (!_webSocketConnections.TryGetValue(id, out webSocket)) { RNTracer.Write( ReactConstants.Tag, Invariant($"Cannot close WebSocket. Unknown WebSocket id {id}.")); return; } try { webSocket.Close(); } catch (Exception ex) { if (_webSocketConnections.ContainsKey(id)) { _webSocketConnections.Remove(id); } RNTracer.Error( ReactConstants.Tag, Invariant($"Could not close WebSocket connection for id '{id}'."), ex); } }
public /* TODO: internal? */ void InvokeFunction(string module, string method, JArray arguments, string tracingName) { QueueConfiguration.JavaScriptQueueThread.RunOnQueue(() => { QueueConfiguration.JavaScriptQueueThread.AssertOnThread(); if (IsDisposed) { return; } using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, tracingName).Start()) { if (_bridge == null) { throw new InvalidOperationException("Bridge has not been initialized."); } _bridge.CallFunction(module, method, arguments); } var eventname = arguments[0].ToString(); CollectGC(eventname); }); }
/// <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); if (jsonObject != null) { 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) { RNTracer.Error(ReactConstants.Tag, "Failure deserializing debug server exception message.", ex); } } return(null); }
/// <summary> /// Updates the layout of a view. /// </summary> /// <param name="parentTag">The parent view tag.</param> /// <param name="tag">The view tag.</param> /// <param name="dimensions">The dimensions.</param> public void UpdateLayout(int parentTag, int tag, Dimensions dimensions) { DispatcherHelpers.AssertOnDispatcher(); //Log.Info(ReactConstants.Tag, "[NativeViewHierarcyManager.UpdateLayout] parentTag:"+parentTag+", tag:"+tag); using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_VIEW, "NativeViewHierarcyManager.UpdateLayout") .With("parentTag", parentTag) .With("tag", tag) .Start()) { // obtain the view to be updated via 'tag' var viewToUpdate = ResolveView(tag); // obtain the specific view manager for updating current view var viewManager = ResolveViewManager(tag); //Log.Info(ReactConstants.Tag, "[NativeViewHierarcyManager.UpdateLayout] viewToUpdate:" + viewToUpdate + ", viewManager:" + viewManager); // check the vilidity of view manager var parentViewManager = default(IViewManager); var parentViewBoxManager = default(IViewParentManager); if (!_tagsToViewManagers.TryGetValue(parentTag, out parentViewManager) || (parentViewBoxManager = parentViewManager as IViewParentManager) == null) { throw new InvalidOperationException( Invariant($"Trying to use view with tag '{tag}' as a parent, but its manager doesn't extend ViewParentManager.")); } if (!parentViewBoxManager.NeedsCustomLayoutForChildren) { UpdateLayout(viewToUpdate, viewManager, dimensions); } } }
//TODO: Microsoft had not support permanent storage yet, //so use our implement instead temp private T GetSetting <T>(string key, T defaultValue) { if (defaultValue is bool) { var ret = ReactConfig.GetValue(key); if (ret != null) { if (ret == "true") { Object data = true; return((T)data); } else { Object data = false; return((T)data); } } } else if (defaultValue is string) { var ret = ReactConfig.GetValue(key); if (ret != null) { Object data = ret; return((T)data); } } else { RNTracer.Write(ReactConstants.Tag, "[RN_EXCEPTION]ERROR! ReactNative.DevSupport.DevInternalSettings GetSetting encounter unexpected type, key is " + key); } return(defaultValue); }
public async Task InitializeBridgeAsync() { await _bundleLoader.InitializeAsync().ConfigureAwait(false); using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "initializeBridge").Start()) { _bridge = await QueueConfiguration.JavaScriptQueueThread.CallOnQueue(() => { QueueConfiguration.JavaScriptQueueThread.AssertOnThread(); var jsExecutor = _jsExecutorFactory(); var bridge = default(ReactBridge); using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "ReactBridgeCtor").Start()) { bridge = new ReactBridge( jsExecutor, new NativeModulesReactCallback(this), QueueConfiguration.NativeModulesQueueThread); } return(bridge); }).ConfigureAwait(false); await QueueConfiguration.JavaScriptQueueThread.CallOnQueue(() => { using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "setBatchedBridgeConfig").Start()) { string moduleConfig = null; bool firstTime = true; string configPath = Tizen.Applications.Application.Current.DirectoryInfo.Data + "moduleConfig.data"; firstTime = !File.Exists(configPath); if (firstTime) { RNTracer.Write(ReactConstants.Tag, "FirstTime output to configPath = " + configPath); moduleConfig = BuildModulesConfig(); File.WriteAllText(configPath, moduleConfig); } else { RNTracer.Write(ReactConstants.Tag, "Get config from configPath = " + configPath); moduleConfig = File.ReadAllText(configPath); } _bridge.SetGlobalVariable("__fbBatchedBridgeConfig", moduleConfig); //Console.WriteLine(">>>>>>> BatchedBridgeConfig: "+ BuildModulesConfig()); } /* TODO: Comment temporarily for skipping bundle js's laoding BOY.YANG 2017-02-18 */ /* use try...catch to capture the core info */ _bundleLoader.LoadScript(_bridge); return(default(object)); }).ConfigureAwait(false); } }
//TODO: Use log to instead temporarily, //need to decide whether to show these failures on error window public void HandleException(Exception exception) { //await Dispatcher.CurrentDispatcher.InvokeAsync(() => //{ // ExceptionDispatchInfo.Capture(exception).Throw(); //}, DispatcherPriority.Send).Task.ConfigureAwait(false); RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION] DisabledDevSupportManager::HandleException:[" + exception.ToString() + "]"); MainSynchronizationContext.Quit(); }
private void CalculateRootLayout(ReactShadowNode cssRoot) { using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "ReactShadowNode.CalculateLayout") .With("RootTag", cssRoot.ReactTag) .Start()) { cssRoot.CalculateLayout(); } }
/// <summary> /// Dispatches the view updates. /// </summary> /// <param name="batchId">The batch identifier.</param> internal void DispatchViewUpdates(int batchId) { var operations = _operations.Count == 0 ? null : _operations; if (operations != null) { _operations = new List <Action>(); } var nonBatchedOperations = default(Action[]); lock (_nonBatchedGate) { if (_nonBatchedOperations.Count > 0) { nonBatchedOperations = _nonBatchedOperations.ToArray(); _nonBatchedOperations.Clear(); } else { nonBatchedOperations = null; } } lock (_gate) { _batches.Add(() => { using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "DispatchUI") .With("BatchId", batchId) .Start()) { if (nonBatchedOperations != null) { foreach (var operation in nonBatchedOperations) { operation(); } } if (operations != null) { foreach (var operation in operations) { operation(); } } _nativeViewHierarchyManager.ClearLayoutAnimation(); } }); } //Running batches async MainSynchronizationContext.Post(FlushPendingBatches); }
/// <summary> /// Hook to notify modules that the <see cref="IReactInstance"/> has /// been disposed. /// </summary> internal void NotifyReactInstanceDispose() { DispatcherHelpers.AssertOnDispatcher(); using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "NativeModuleRegistry_NotifyReactInstanceDestroy").Start()) { foreach (var module in _moduleInstances.Values) { module.OnReactInstanceDispose(); } } }
/// <summary> /// To implement the transactional requirement, UI changes are only /// committed to the actual view hierarchy once a batch of JavaScript /// to native calls have been completed. /// </summary> public void OnBatchComplete() { var batchId = _batchId++; using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "onBatchCompleteUI") .With("BatchId", batchId) .Start()) { _uiImplementation.DispatchViewUpdates(_eventDispatcher, batchId); } }
/// <summary> /// Write the module descriptions to the given <see cref="JsonWriter"/>. /// </summary> /// <param name="writer">The JSON writer.</param> internal void WriteModuleDescriptions(JsonWriter writer) { using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "CreateJSON").Start()) { writer.WriteStartArray(); foreach (var moduleDef in _moduleTable) { moduleDef.WriteModuleDescription(writer); } writer.WriteEndArray(); } }
private void ScheduleDispatch(object sender, object e) { DispatcherHelpers.AssertOnDispatcher(); var activity = RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "ScheduleDispatch").Start(); MoveStagedEventsToDispatchQueue(); if (!Volatile.Read(ref _hasDispatchScheduled)) { _hasDispatchScheduled = true; _reactContext.RunOnJavaScriptQueueThread(() => DispatchEvents(activity)); } }
public void OnBatchComplete() { _parent.QueueConfiguration.NativeModulesQueueThread.AssertOnThread(); // The bridge may have been destroyed due to an exception // during the batch. In that case native modules could be in a // bad state so we don't want to call anything on them. if (!_parent.IsDisposed) { using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "OnBatchComplete").Start()) { _parent._registry.OnBatchComplete(); } } }
public void ShowNewNativeError(string message, Exception exception) { var javaScriptException = exception as JavaScriptException; if (javaScriptException != null && javaScriptException.JavaScriptStackTrace != null) { var stackTrace = StackTraceHelper.ConvertJSCoreStackTrace(javaScriptException.JavaScriptStackTrace); ShowNewError(exception.Message, stackTrace, NativeErrorCookie); } else { RNTracer.Error(ReactConstants.Tag, "Exception in native call from JavaScript.", exception); ShowNewError(message, StackTraceHelper.ConvertNativeStackTrace(exception), NativeErrorCookie); } }
/// <summary> /// Queues an action to run. /// </summary> /// <param name="action">The action.</param> public void RunOnQueue(Action action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (IsDisposed) { RNTracer.Write(ReactConstants.Tag, Invariant($"Dropping enqueued action on disposed '{_name}' thread.")); return; } Enqueue(action); }
/// <summary> /// Method that gives JavaScript the opportunity to consume the back /// button event. If JavaScript does not consume the event, the /// default back press action will be invoked at the end of the /// round trip to JavaScript. /// </summary> public void OnBackPressed() { DispatcherHelpers.AssertOnDispatcher(); var reactContext = _currentReactContext; if (reactContext == null) { RNTracer.Write(ReactConstants.Tag, "Instance detached from instance manager."); InvokeDefaultOnBackPressed(); } else { reactContext.GetNativeModule <DeviceEventManagerModule>().EmitHardwareBackPressed(); } Log.Debug(ReactConstants.Tag, "## Inform JS of Back button being Pressed ##"); }
public void UpdateJavaScriptError(string message, JArray details, int errorCookie) { DispatcherHelpers.RunOnDispatcher(() => { if (_redBoxDialog == null || !_redBoxDialogOpen || errorCookie != _redBoxDialog.ErrorCookie) { return; } _redBoxDialog.Message = message; _redBoxDialog.StackTrace = StackTraceHelper.ConvertJavaScriptStackTrace(details); }); RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION] DevSupportManager::UpdateJavaScriptError:[" + message + "]"); }
private async Task InitializeReactContextAsync( Func <IJavaScriptExecutor> jsExecutorFactory, JavaScriptBundleLoader jsBundleLoader) { Log.Info(ReactConstants.Tag, "## Enter InitializeReactContextAsync ##"); var currentReactContext = _currentReactContext; if (currentReactContext != null) { await TearDownReactContextAsync(currentReactContext); _currentReactContext = null; } try { Log.Info(ReactConstants.Tag, "## CreateReactContextAsync(jsExecutorFactory, jsBundleLoader) ##"); var reactContext = await CreateReactContextAsync(jsExecutorFactory, jsBundleLoader); using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "SetupReactContext").Start()) { SetupReactContext(reactContext); } } catch (Exception ex) { _devSupportManager.HandleException(ex); } finally { _contextInitializationTask = null; } if (_pendingJsExecutorFactory != null) { var pendingJsExecutorFactory = _pendingJsExecutorFactory; var pendingJsBundleLoader = _pendingJsBundleLoader; _pendingJsExecutorFactory = null; _pendingJsBundleLoader = null; RecreateReactContextInBackground( pendingJsExecutorFactory, pendingJsBundleLoader); } }
public IReadOnlyList <INativeModule> CreateNativeModules(ReactContext reactContext) { var uiManagerModule = default(INativeModule); using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "createUIManagerModule").Start()) { var viewManagerList = _reactInstanceManager.CreateAllViewManagers(reactContext); #if WINDOWS_UWP uiManagerModule = new UIManagerModule( reactContext, viewManagerList, _uiImplementationProvider.Create( reactContext, viewManagerList)); #else uiManagerModule = new UIManagerModule( reactContext, viewManagerList, _uiImplementationProvider.Create( reactContext, viewManagerList, new EventDispatcher(reactContext)), ReactProgram.RctWindow); #endif } return(new List <INativeModule> { /*new AnimationsDebugModule( * reactContext, * _reactInstanceManager.DevSupportManager.DevSettings),*/ //new SystemInfoModule(), new DeviceEventManagerModule(reactContext, _hardwareBackButtonHandler), new ExceptionsManagerModule(_reactInstanceManager.DevSupportManager), new Timing(reactContext), new TVNavigationEventEmitter(reactContext), new SourceCodeModule( _reactInstanceManager.SourceUrl, _reactInstanceManager.DevSupportManager.SourceMapUrl), uiManagerModule, //new DebugComponentOwnershipModule(reactContext), }); }
/// <summary> /// Uses the configured <see cref="IReactPackage"/> instances to create /// all <see cref="IViewManager"/> instances. /// </summary> /// <param name="reactContext"> /// The application context. /// </param> /// <returns>The list of view managers.</returns> public IReadOnlyList <IViewManager> CreateAllViewManagers(ReactContext reactContext) { if (reactContext == null) { throw new ArgumentNullException(nameof(reactContext)); } using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "createAllViewManagers").Start()) { var allViewManagers = new List <IViewManager>(); foreach (var package in _packages) { allViewManagers.AddRange( package.CreateViewManagers(reactContext)); } return(allViewManagers); } }
/// <summary> /// Registers a new root view. /// </summary> /// <param name="rootView">The root view instance.</param> /// <returns>The root view tag.</returns> /// <remarks> /// JavaScript can use the returned tag with to add or remove children /// to this view through <see cref="manageChildren(int, int[], int[], int[], int[], int[])"/>. /// </remarks> public int AddMeasuredRootView(SizeMonitoringCanvas rootView) { var tag = _nextRootTag; _nextRootTag += RootViewTagIncrement; //var width = rootView.ActualWidth; //var height = rootView.ActualHeight; var geometry = rootView.Geometry; var width = geometry.Width; var height = geometry.Height; RNTracer.Write(Common.ReactConstants.Tag, "RootView : " + width + " * " + height); var context = new ThemedReactContext(Context); _uiImplementation.RegisterRootView(rootView, tag, width, height, context); var resizeCount = 0; rootView.SetOnSizeChangedListener((sender, args) => { var currentCount = ++resizeCount; /* * var newWidth = args.NewSize.Width; * var newHeight = args.NewSize.Height; * * Context.RunOnNativeModulesQueueThread(() => * { * if (currentCount == resizeCount) * { * Context.AssertOnNativeModulesQueueThread(); * _uiImplementation.UpdateRootNodeSize(tag, newWidth, newHeight, _eventDispatcher); * } * }); */ }); return(tag); }
private void FlushPendingBatches() { lock (_gate) { try { foreach (var batch in _batches) { batch(); } } catch (Exception ex) { RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION]At batch:[" + ex.ToString() + "]"); } finally { _batches.Clear(); } } }
//TODO: Microsoft had not support permanent storage yet, //so use our implement instead temp private void SetSetting <T>(string key, T value) { if (value is bool) { ReactConfig.SetValue(key, value.ToString().ToLower()); } else if (value is string) { ReactConfig.SetValue(key, value.ToString()); } else { RNTracer.Write(ReactConstants.Tag, "[RN_EXCEPTION]ERROR! ReactNative.DevSupport.DevInternalSettings GetSetting encounter unexpected type"); return; } if (s_triggerReload.Contains(key)) { _debugManager.ReloadSettings(); } }
protected override async void Enqueue(Action action) { await _taskFactory.StartNew(() => { try { lock (_gate) { if (!IsDisposed) { action(); } } } catch (Exception ex) { RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION]At action:[" + ex.ToString() + "]"); _handler(ex); } }).ConfigureAwait(false); }
private void Run() { while (true) { var action = _queue.Take(); if (IsDisposed) { break; } try { action(); } catch (Exception ex) { RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION]At action:[" + ex.ToString() + "]"); _handler(ex); } } }
public void InvokeCallback(int callbackId, JArray arguments) { if (IsDisposed) { RNTracer.Write(ReactConstants.Tag, "Invoking JS callback after bridge has been destroyed."); return; } QueueConfiguration.JavaScriptQueueThread.RunOnQueue(() => { QueueConfiguration.JavaScriptQueueThread.AssertOnThread(); if (IsDisposed) { return; } using (RNTracer.Trace(RNTracer.TRACE_TAG_REACT_BRIDGE, "<callback>").Start()) { _bridge.InvokeCallback(callbackId, arguments); } }); }
//TODO: Use log to instead temporarily private void ShowNewError(string message, IStackFrame[] stack, int errorCookie) { RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION] DevSupportManager::ShowNewError:[" + message + "]"); DispatcherHelpers.RunOnDispatcher(() => { if (_redBoxDialog == null) { _redBoxDialog = new RedBoxDialog(HandleReloadJavaScript); } if (_redBoxDialogOpen) { return; } _redBoxDialogOpen = true; _redBoxDialog.ErrorCookie = errorCookie; _redBoxDialog.Message = message; _redBoxDialog.StackTrace = stack; _redBoxDialog.Closed += (_, __) => { _redBoxDialogOpen = false; _dismissRedBoxDialog = null; _redBoxDialog = null; }; //if (Application.Current != null && Application.Current.MainWindow != null && Application.Current.MainWindow.IsLoaded) //{ // _redBoxDialog.Owner = Application.Current.MainWindow; //} //else //{ // _redBoxDialog.Topmost = true; // _redBoxDialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; //} _dismissRedBoxDialog = _redBoxDialog.Close; _redBoxDialog.Show(); }); }
private void OnMessageReceived(object sender, Websockets.Net.MessageEventArgs args) { var response = args; var json = JObject.Parse(response.Data); if (json != null) { if (json.ContainsKey("replyID")) { var replyId = json.Value <int>("replyID"); var callback = default(TaskCompletionSource <JToken>); if (_callbacks.TryGetValue(replyId, out callback)) { var result = default(JToken); if (json.TryGetValue("result", out result)) { if (result.Type == JTokenType.String) { callback.TrySetResult(JToken.Parse(result.Value <string>())); } else { callback.TrySetResult(result); } } else { callback.TrySetResult(null); } } } } else { RNTracer.Write(ReactConstants.Tag, "Fatal Error in WebSocketJavaScriptExecutor OnMessageReceived, json is null"); } }
public static string GetValue(string key) { try { using (FileStream fileStream = new FileStream(LocalDataFile, FileMode.OpenOrCreate)) { if (fileStream.Length == 0) { return(null); } XmlSerializer xmlFormatter = new XmlSerializer(typeof(SerializableDictionary <string, string>)); SerializableDictionary = (SerializableDictionary <string, string>)xmlFormatter.Deserialize(fileStream); } string ret = null; SerializableDictionary.TryGetValue(key, out ret); return(ret); } catch (Exception ex) { RNTracer.Error(ReactConstants.Tag, "[RN_EXCEPTION]At ReactConfig GetValue:[" + ex.ToString() + "]"); return(null); } }