From 0b34346c195eea7341a8dd7ec3a06ebb3f14048e Mon Sep 17 00:00:00 2001 From: Michael Mauderer Date: Mon, 16 May 2022 13:28:50 +0100 Subject: [PATCH] Improve profiling for UI interactions v2. (#3451) * Extends the instrumentation of the code base and upgrades some FRPs to the newer API macro. * Extends the run-graph demo scene to specify a profile via URL without recompilation. * Fixes labels in the flame graph demo scene. * Fixes an issue with loading profiles that contains escaped characters. # Important Notes * no longer contains the upgrade of the `text::View` to `define_endpoints_2`. This should be fixed as part of the text rendering rewrite. [ci no changelog needed] --- Cargo.lock | 13 + app/gui/language/ast/impl/Cargo.toml | 1 + app/gui/language/ast/impl/src/crumbs.rs | 2 +- app/gui/language/parser/src/lib.rs | 1 + app/gui/src/controller/graph.rs | 2 + app/gui/src/controller/ide.rs | 3 + app/gui/src/controller/searcher.rs | 12 + app/gui/src/controller/searcher/action.rs | 3 + app/gui/src/ide.rs | 12 +- app/gui/src/model/undo_redo.rs | 1 + app/gui/src/presenter/searcher.rs | 6 + .../view/graph-editor/src/component/node.rs | 15 + .../src/component/node/input/area.rs | 60 ++- .../src/component/node/input/port.rs | 1 + .../src/component/node/output/area.rs | 54 +- app/ide-desktop/package-lock.json | 501 +++++++++--------- build/run.js | 2 +- .../component/text/src/component/area.rs | 23 + lib/rust/ensogl/core/src/display/garbage.rs | 4 + .../src/display/shape/primitive/system.rs | 8 + lib/rust/ensogl/core/src/display/world.rs | 2 + lib/rust/ensogl/core/src/gui/cursor.rs | 13 +- .../example/profiling-run-graph/Cargo.toml | 2 + .../example/profiling-run-graph/src/lib.rs | 51 +- .../render-profile-flamegraph/Cargo.toml | 2 + .../render-profile-flamegraph/src/lib.rs | 18 +- lib/rust/frp/src/stream.rs | 2 +- lib/rust/profiler/data/src/bin/intervals.rs | 1 - lib/rust/profiler/data/src/parse.rs | 2 +- lib/rust/profiler/flame-graph/src/lib.rs | 37 +- lib/rust/profiler/src/format.rs | 15 +- lib/rust/profiler/src/format/builder.rs | 1 + 32 files changed, 544 insertions(+), 326 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20346b911b7..884593b204b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,6 +91,7 @@ dependencies = [ "derive_more", "enso-data-structures", "enso-prelude", + "enso-profiler", "enso-shapely", "enso-text", "failure", @@ -1517,7 +1518,9 @@ dependencies = [ "ensogl-text-msdf-sys", "ensogl-tooltip", "futures 0.3.21", + "qstring", "serde", + "url 2.2.2", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1537,6 +1540,7 @@ dependencies = [ "ensogl-hardcoded-theme", "ensogl-text", "ensogl-text-msdf-sys", + "ensogl-tooltip", "futures 0.3.21", "wasm-bindgen", "wasm-bindgen-futures", @@ -3366,6 +3370,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding 2.1.0", +] + [[package]] name = "quote" version = "1.0.18" diff --git a/app/gui/language/ast/impl/Cargo.toml b/app/gui/language/ast/impl/Cargo.toml index c1f525a2a85..3ab46277d6b 100644 --- a/app/gui/language/ast/impl/Cargo.toml +++ b/app/gui/language/ast/impl/Cargo.toml @@ -21,3 +21,4 @@ enso-data-structures = { path = "../../../../../lib/rust/data-structures" } enso-text = { path = "../../../../../lib/rust/text" } enso-prelude = { path = "../../../../../lib/rust/prelude" } enso-shapely = { path = "../../../../../lib/rust/shapely" } +enso-profiler = { path = "../../../../../lib/rust/profiler" } diff --git a/app/gui/language/ast/impl/src/crumbs.rs b/app/gui/language/ast/impl/src/crumbs.rs index 4d6abe6fc7e..beb1e8356a0 100644 --- a/app/gui/language/ast/impl/src/crumbs.rs +++ b/app/gui/language/ast/impl/src/crumbs.rs @@ -1464,7 +1464,7 @@ pub trait TraversableAst: Sized { self.get_traversing(&[]) } - /// Calculate the span of the descendent AST node described by given crumbs.. + /// Calculate the span of the descendent AST node described by given crumbs. fn range_of_descendant_at(&self, crumbs: &[Crumb]) -> FallibleResult> { let mut position = 0.bytes(); let mut ast = self.my_ast()?; diff --git a/app/gui/language/parser/src/lib.rs b/app/gui/language/parser/src/lib.rs index 020affed0fc..9ef7f5ec032 100644 --- a/app/gui/language/parser/src/lib.rs +++ b/app/gui/language/parser/src/lib.rs @@ -120,6 +120,7 @@ impl Parser { /// Program is expected to be single non-empty line module. The line's AST is /// returned. The program is parsed with empty IdMap. + #[profile(Debug)] pub fn parse_line_ast(&self, program: impl Str) -> FallibleResult { self.parse_line_with_id_map(program, default()).map(|line| line.elem) } diff --git a/app/gui/src/controller/graph.rs b/app/gui/src/controller/graph.rs index c6ddd8053e7..6d8fc3b4a41 100644 --- a/app/gui/src/controller/graph.rs +++ b/app/gui/src/controller/graph.rs @@ -841,6 +841,7 @@ impl Handle { } /// Sets the given's node expression. + #[profile(Debug)] pub fn set_expression_ast(&self, id: ast::Id, expression: Ast) -> FallibleResult { info!(self.logger, "Setting node {id} expression to `{expression.repr()}`"); self.update_definition_ast(|definition| { @@ -1052,6 +1053,7 @@ pub mod tests { self.module_path.method_pointer(self.project_name.clone(), self.graph_id.to_string()) } + #[profile(Debug)] pub fn suggestion_db(&self) -> Rc { use model::suggestion_database::SuggestionDatabase; let entries = self.suggestions.iter(); diff --git a/app/gui/src/controller/ide.rs b/app/gui/src/controller/ide.rs index 1572ba52f9d..b0503c9b4ae 100644 --- a/app/gui/src/controller/ide.rs +++ b/app/gui/src/controller/ide.rs @@ -56,6 +56,7 @@ impl StatusNotificationPublisher { } /// Publish a new status event (see [`StatusNotification::Event`]) + #[profile(Debug)] pub fn publish_event(&self, label: impl Into) { let label = label.into(); let notification = StatusNotification::Event { label }; @@ -65,6 +66,7 @@ impl StatusNotificationPublisher { /// Publish a notification about new process (see [`StatusNotification::ProcessStarted`]). /// /// Returns the handle to be used when notifying about process finishing. + #[profile(Debug)] pub fn publish_background_task(&self, label: impl Into) -> BackgroundTaskHandle { let label = label.into(); let handle = self.next_process_handle.get(); @@ -76,6 +78,7 @@ impl StatusNotificationPublisher { /// Publish a notfication that process has finished (see /// [`StatusNotification::ProcessFinished`]) + #[profile(Debug)] pub fn published_background_task_finished(&self, handle: BackgroundTaskHandle) { let notification = StatusNotification::BackgroundTaskFinished { handle }; executor::global::spawn(self.publisher.publish(notification)); diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 561e4fdee50..dc998cf0e16 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -194,6 +194,7 @@ pub struct ParsedInput { impl ParsedInput { /// Constructor from the plain input. + #[profile(Debug)] fn new(input: impl Into, parser: &Parser) -> FallibleResult { let mut input = input.into(); let leading_spaces = input.chars().take_while(|c| *c == ' ').count(); @@ -421,6 +422,7 @@ impl Data { /// Committing node will then edit the exiting node's expression instead of adding a new one. /// Additionally searcher should restore information about intended method, so we will be able /// to suggest arguments. + #[profile(Debug)] fn new_with_edited_node( project_name: project::QualifiedName, graph: &controller::Graph, @@ -498,6 +500,7 @@ impl Searcher { } /// Create new Searcher Controller, when you have Executed Graph Controller handy. + #[profile(Task)] pub fn new_from_graph_controller( parent: impl AnyLogger, ide: controller::Ide, @@ -563,6 +566,7 @@ impl Searcher { /// /// This function should be called each time user modifies Searcher input in view. It may result /// in a new action list (the appropriate notification will be emitted). + #[profile(Debug)] pub fn set_input(&self, new_input: String) -> FallibleResult { debug!(self.logger, "Manually setting input to {new_input}."); let parsed_input = ParsedInput::new(new_input, self.ide.parser())?; @@ -600,6 +604,7 @@ impl Searcher { /// This function should be called when user do the _use as suggestion_ action as a code /// suggestion (see struct documentation). The picked suggestion will be remembered, and the /// searcher's input will be updated and returned by this function. + #[profile(Debug)] pub fn use_suggestion(&self, picked_suggestion: action::Suggestion) -> FallibleResult { info!(self.logger, "Picking suggestion: {picked_suggestion:?}"); let id = self.data.borrow().input.next_completion_id(); @@ -695,6 +700,7 @@ impl Searcher { } /// See `execute_action` documentation. + #[profile(Task)] pub fn execute_action_by_index(&self, index: usize) -> FallibleResult> { let error = || NoSuchAction { index }; let action = { @@ -724,6 +730,7 @@ impl Searcher { /// If the searcher was brought by editing existing node, the input is set as a new node /// expression, otherwise a new node is added. This will also add all imports required by /// picked suggestions. + #[profile(Debug)] pub fn commit_node(&self) -> FallibleResult { let _transaction_guard = self.graph.get_or_open_transaction("Commit node"); let expr_and_method = || { @@ -772,6 +779,7 @@ impl Searcher { /// /// The example piece of code will be inserted as a new function definition, and in current /// graph the node calling this function will appear. + #[profile(Debug)] pub fn add_example( &self, example: &action::Example, @@ -814,6 +822,7 @@ impl Searcher { Ok(added_node_id) } + #[profile(Debug)] fn invalidate_fragments_added_by_picking(&self) { let mut data = self.data.borrow_mut(); let data = data.deref_mut(); @@ -844,6 +853,7 @@ impl Searcher { /// /// The current list will be set as "Loading" and Language Server will be requested for a new /// list - once it be retrieved, the new list will be set and notification will be emitted. + #[profile(Debug)] fn reload_list(&self) { let this_type = self.this_arg_type_for_next_completion(); let return_types = match self.data.borrow().input.next_completion_id() { @@ -858,6 +868,7 @@ impl Searcher { /// Get the typename of "this" value for current completion context. Returns `Future`, as the /// type information might not have came yet from the Language Server. + #[profile(Debug)] fn this_arg_type_for_next_completion(&self) -> impl Future> { let next_id = self.data.borrow().input.next_completion_id(); let logger = self.logger.clone_ref(); @@ -931,6 +942,7 @@ impl Searcher { } /// Process multiple completion responses from the engine into a single list of suggestion. + #[profile(Debug)] fn make_action_list( &self, completion_responses: Vec>, diff --git a/app/gui/src/controller/searcher/action.rs b/app/gui/src/controller/searcher/action.rs index 12a784bd687..55c342c607b 100644 --- a/app/gui/src/controller/searcher/action.rs +++ b/app/gui/src/controller/searcher/action.rs @@ -240,6 +240,7 @@ impl ListEntry { /// The ordering on the action list: first, are the matched entries are gathered on the top of /// the list, then sorted by categories, and those of same category are ordered by match score /// (the best matches are first). + #[profile(Debug)] pub fn ordering_on_list(&self, rhs: &Self) -> std::cmp::Ordering { self.matches() .cmp(&rhs.matches()) @@ -297,6 +298,7 @@ impl List { /// /// The "matching score" of each entry is recalculated against the given pattern and the entries /// are re-ordered, so the best matches will go first. + #[profile(Debug)] pub fn update_filtering(&self, pattern: impl Str) { { let mut entries_mut = self.entries.borrow_mut(); @@ -370,6 +372,7 @@ impl List { self.entries.borrow().iter().map(|entry| entry.action.clone_ref()).collect() } + #[profile(Debug)] fn update_sorting(&self) { let mut entries_mut = self.entries.borrow_mut(); entries_mut.sort_by(|l, r| l.ordering_on_list(r)); diff --git a/app/gui/src/ide.rs b/app/gui/src/ide.rs index 99a2a29bd7e..44c7cd6d30c 100644 --- a/app/gui/src/ide.rs +++ b/app/gui/src/ide.rs @@ -74,13 +74,13 @@ impl Ide { enso_frp::extend! { network on_log_sent <- source::<()>(); - mouse_moved <- mouse.position.constant(()); - any_mouse_press <- any(mouse.up,mouse.down).constant(()); - any_mouse_event <- any(any_mouse_press,mouse_moved,mouse.wheel); - any_keyboard_event <- any(keyboard.down,keyboard.up).constant(()); - any_input_event <- any(any_mouse_event,any_keyboard_event); + mouse_moved <- mouse.position.constant(()).profile(); + any_mouse_press <- any(mouse.up,mouse.down).constant(()).profile(); + any_mouse_event <- any(any_mouse_press,mouse_moved,mouse.wheel).profile(); + any_keyboard_event <- any(keyboard.down,keyboard.up).constant(()).profile(); + any_input_event <- any(any_mouse_event,any_keyboard_event).profile(); // True if any input event was captured since the last "alive" log sending. - input_event_received <- bool(&on_log_sent,&any_input_event).sampler(); + input_event_received <- bool(&on_log_sent,&any_input_event).profile().sampler(); } async move { loop { diff --git a/app/gui/src/model/undo_redo.rs b/app/gui/src/model/undo_redo.rs index 88e6d745692..f449135eb3d 100644 --- a/app/gui/src/model/undo_redo.rs +++ b/app/gui/src/model/undo_redo.rs @@ -52,6 +52,7 @@ pub trait Aware { fn undo_redo_repository(&self) -> Rc; /// Get current ongoing transaction. If there is no ongoing transaction, create a one. + #[profile(Debug)] #[must_use] fn get_or_open_transaction(&self, name: &str) -> Rc { self.undo_redo_repository().transaction(name) diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index 2c55cd34808..e02306b7c3d 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -37,6 +37,7 @@ struct Model { } impl Model { + #[profile(Debug)] fn new( parent: impl AnyLogger, controller: controller::Searcher, @@ -47,6 +48,7 @@ impl Model { Self { logger, controller, view, input_view } } + #[profile(Debug)] fn input_changed(&self, new_input: &str) { if let Err(err) = self.controller.set_input(new_input.to_owned()) { error!(self.logger, "Error while setting new searcher input: {err}"); @@ -69,6 +71,7 @@ impl Model { } } + #[profile(Task)] fn commit_editing(&self, entry_id: Option) -> Option { let result = match entry_id { Some(id) => self.controller.execute_action_by_index(id), @@ -107,6 +110,7 @@ pub struct Searcher { impl Searcher { /// Constructor. The returned structure works rigth away. + #[profile(Task)] pub fn new( parent: impl AnyLogger, controller: controller::Searcher, @@ -151,6 +155,7 @@ impl Searcher { /// Setup new, appropriate searcher controller for the edition of `node_view`, and construct /// presenter handling it. + #[profile(Task)] pub fn setup_controller( parent: impl AnyLogger, ide_controller: controller::Ide, @@ -189,6 +194,7 @@ impl Searcher { /// editing finishes. The `entry_id` might be none in case where the searcher should accept /// the node input without any entry selected. If the commitment will result in creating a new /// node, its AST id is returned. + #[profile(Task)] pub fn commit_editing(self, entry_id: Option) -> Option { self.model.commit_editing(entry_id) } diff --git a/app/gui/view/graph-editor/src/component/node.rs b/app/gui/view/graph-editor/src/component/node.rs index 97a4fc1d13d..b7c1384a6a2 100644 --- a/app/gui/view/graph-editor/src/component/node.rs +++ b/app/gui/view/graph-editor/src/component/node.rs @@ -438,6 +438,7 @@ pub struct NodeModel { impl NodeModel { /// Constructor. + #[profile(Debug)] pub fn new(app: &Application, registry: visualization::Registry) -> Self { ensogl::shapes_order_dependencies! { app.display.default_scene => { @@ -528,17 +529,20 @@ impl NodeModel { .init() } + #[profile(Debug)] #[allow(missing_docs)] // FIXME[everyone] All pub functions should have docs. pub fn get_crumbs_by_id(&self, id: ast::Id) -> Option { let input_crumbs = self.input.get_crumbs_by_id(id).map(Crumbs::input); input_crumbs.or_else(|| self.output.get_crumbs_by_id(id).map(Crumbs::output)) } + #[profile(Debug)] fn init(self) -> Self { self.set_expression(Expression::new_plain("empty")); self } + #[profile(Debug)] fn set_layers(&self, layer: &Layer, text_layer: &Layer, action_bar_layer: &Layer) { layer.add_exclusive(&self.display_object); action_bar_layer.add_exclusive(&self.action_bar); @@ -555,6 +559,7 @@ impl NodeModel { /// /// `action_bar` is moved to the `edited_node` layer as well, though normally it lives on a /// separate `above_nodes` layer, unlike every other node component. + #[profile(Debug)] pub fn move_to_edited_node_layer(&self) { let scene = &self.app.display.default_scene; let layer = &scene.layers.edited_node; @@ -570,6 +575,7 @@ impl NodeModel { /// /// `action_bar` is handled separately, as it uses `above_nodes` scene layer unlike any other /// node component. + #[profile(Debug)] pub fn move_to_main_layer(&self) { let scene = &self.app.display.default_scene; let layer = &scene.layers.main; @@ -588,12 +594,14 @@ impl NodeModel { HEIGHT } + #[profile(Debug)] fn set_expression(&self, expr: impl Into) { let expr = expr.into(); self.output.set_expression(&expr); self.input.set_expression(&expr); } + #[profile(Debug)] fn set_expression_usage_type(&self, crumbs: &Crumbs, tp: &Option) { match crumbs.endpoint { Endpoint::Input => self.input.set_expression_usage_type(&crumbs.crumbs, tp), @@ -601,6 +609,7 @@ impl NodeModel { } } + #[profile(Debug)] fn set_width(&self, width: f32) -> Vector2 { let height = self.height(); let size = Vector2(width, height); @@ -630,11 +639,13 @@ impl NodeModel { size } + #[profile(Debug)] #[allow(missing_docs)] // FIXME[everyone] All pub functions should have docs. pub fn visualization(&self) -> &visualization::Container { &self.visualization } + #[profile(Debug)] fn set_error(&self, error: Option<&Error>) { if let Some(error) = error { self.error_visualization.display_kind(*error.kind); @@ -647,6 +658,7 @@ impl NodeModel { } } + #[profile(Debug)] fn set_error_color(&self, color: &color::Lcha) { self.error_indicator.color_rgba.set(color::Rgba::from(color).into()); if color.alpha < EPSILON { @@ -659,6 +671,7 @@ impl NodeModel { impl Node { #[allow(missing_docs)] // FIXME[everyone] All pub functions should have docs. + #[profile(Debug)] pub fn new(app: &Application, registry: visualization::Registry) -> Self { let frp = Frp::new(); let network = &frp.private.network; @@ -954,6 +967,7 @@ impl Node { Node { widget } } + #[profile(Debug)] fn error_color(error: &Option, style: &StyleWatch) -> color::Lcha { use ensogl_hardcoded_theme::graph_editor::node::error as error_theme; @@ -988,6 +1002,7 @@ fn visualization_offset(node_width: f32) -> Vector2 { Vector2(x_offset_to_node_center(node_width), VISUALIZATION_OFFSET_Y) } +#[profile(Debug)] fn bounding_box( node_position: Vector2, node_size: Vector2, diff --git a/app/gui/view/graph-editor/src/component/node/input/area.rs b/app/gui/view/graph-editor/src/component/node/input/area.rs index 9598e90be45..e4a8e7bf8a9 100644 --- a/app/gui/view/graph-editor/src/component/node/input/area.rs +++ b/app/gui/view/graph-editor/src/component/node/input/area.rs @@ -11,10 +11,12 @@ use crate::node; use crate::node::input::port; use crate::node::profiling; use crate::view; +use crate::FrpNetworkProvider; use crate::Type; use enso_frp as frp; use enso_frp; +use enso_frp::stream::ValueProvider; use enso_text::text::Text; use ensogl::application::Application; use ensogl::data::color; @@ -25,7 +27,6 @@ use ensogl_component::text; use ensogl_hardcoded_theme as theme; - // ================= // === Constants === // ================= @@ -166,7 +167,7 @@ impl From for Expression { // === Model === // ============= -ensogl::define_endpoints! { +ensogl::define_endpoints_2! { Input { /// Set the mode in which the cursor will indicate that editing of the node is possible. set_edit_ready_mode (bool), @@ -233,6 +234,7 @@ pub struct Model { impl Model { /// Constructor. + #[profile(Debug)] pub fn new(logger: impl AnyLogger, app: &Application) -> Self { let logger = Logger::new_sub(&logger, "input_ports"); let display_object = display::object::Instance::new(&logger); @@ -262,6 +264,7 @@ impl Model { .init() } + #[profile(Debug)] fn init(self) -> Self { // FIXME[WD]: Depth sorting of labels to in front of the mouse pointer. Temporary solution. // It needs to be more flexible once we have proper depth management. @@ -312,6 +315,7 @@ impl Model { } /// Update expression type for the particular `ast::Id`. + #[profile(Debug)] fn set_expression_usage_type(&self, crumbs: &Crumbs, tp: &Option) { if let Ok(port) = self.expression.borrow().span_tree.root_ref().get_descendant(crumbs) { port.set_usage_type(tp) @@ -351,10 +355,11 @@ impl Deref for Area { impl Area { /// Constructor. + #[profile(Debug)] pub fn new(logger: impl AnyLogger, app: &Application) -> Self { let model = Rc::new(Model::new(logger, app)); let frp = Frp::new(); - let network = &frp.network; + let network = frp.network(); let selection_color = Animation::new(network); frp::extend! { network @@ -364,12 +369,12 @@ impl Area { // learn more about the architecture and the importance of the hover // functionality. - frp.output.source.body_hover <+ frp.set_hover; + frp.private.output.body_hover <+ frp.set_hover; // === Cursor setup === - eval frp.input.set_edit_mode ([model](edit_mode) { + eval frp.private.input.set_edit_mode ([model](edit_mode) { model.label.set_focus(edit_mode); if *edit_mode { // Reset the code to hide non-connected port names. @@ -392,8 +397,8 @@ impl Area { ); port_vis <- all_with(&frp.input.set_ports_active,&edit_mode,|(a,_),b|*a&&(!b)); - frp.output.source.ports_visible <+ port_vis; - frp.output.source.editing <+ edit_mode; + frp.private.output.ports_visible <+ port_vis; + frp.private.output.editing <+ edit_mode; // === Label Hover === @@ -415,8 +420,8 @@ impl Area { // === Properties === width <- model.label.width.map(|t| t + 2.0 * TEXT_OFFSET); - frp.output.source.width <+ width; - frp.output.source.expression <+ model.label.content; + frp.private.output.width <+ width; + frp.private.output.expression <+ model.label.content; // === Expression Type === @@ -426,7 +431,7 @@ impl Area { // === View Mode === - frp.output.source.view_mode <+ frp.set_view_mode; + frp.private.output.view_mode <+ frp.set_view_mode; in_profiling_mode <- frp.view_mode.map(|m| m.is_profiling()); finished <- frp.set_profiling_status.map(|s| s.is_finished()); @@ -518,6 +523,7 @@ struct PortLayerBuilder { impl PortLayerBuilder { /// Constructor. + #[profile(Debug)] fn new( parent: impl display::Object, parent_frp: Option, @@ -534,6 +540,7 @@ impl PortLayerBuilder { } /// Create a nested builder with increased depth and updated `parent_frp`. + #[profile(Debug)] fn nested( &self, parent: display::object::Instance, @@ -548,10 +555,12 @@ impl PortLayerBuilder { } impl Area { + #[profile(Debug)] fn set_label_on_new_expression(&self, expression: &Expression) { self.model.label.set_content(expression.viz_code.clone()); } + #[profile(Debug)] fn build_port_shapes_on_new_expression(&self, expression: &mut Expression) { let mut is_header = true; let mut id_crumbs_map = HashMap::new(); @@ -630,7 +639,7 @@ impl Area { let any_type_sel_color = styles_frp.get_color(theme::code::types::any::selection); let crumbs = port.crumbs.clone_ref(); let port_network = &port.network; - let frp = &self.frp.output; + let frp = &self.frp.private; frp::extend! { port_network @@ -649,7 +658,7 @@ impl Area { // Please note, that this is computed first in order to compute `ports_visible` // when needed, and thus it has to be run before the following lines. - self.frp.output.source.body_hover <+ bool(&mouse_out,&mouse_over_raw); + self.frp.private.output.body_hover <+ bool(&mouse_out,&mouse_over_raw); // TODO[WD] for FRP3: Consider the following code. Here, we have to first // handle `bg_down` and then `mouse_down`. Otherwise, `mouse_down` may @@ -660,21 +669,21 @@ impl Area { // be solved by solving in the FRP engine all children first, and then their // children (then both `bg_down` and `mouse_down` will be resolved before // the `ports_visible` changes). - bg_down <- mouse_down_raw.gate_not(&frp.ports_visible); - mouse_down <- mouse_down_raw.gate(&frp.ports_visible); - mouse_over <- mouse_over_raw.gate(&frp.ports_visible); - self.frp.output.source.on_background_press <+ bg_down; + bg_down <- mouse_down_raw.gate_not(&frp.output.ports_visible); + mouse_down <- mouse_down_raw.gate(&frp.output.ports_visible); + mouse_over <- mouse_over_raw.gate(&frp.output.ports_visible); + self.frp.private.output.on_background_press <+ bg_down; // === Press === - eval_ mouse_down ([crumbs,frp] frp.source.on_port_press.emit(&crumbs)); + eval_ mouse_down ([crumbs,frp] frp.output.on_port_press.emit(&crumbs)); // === Hover === hovered <- bool(&mouse_out,&mouse_over); hover <- hovered.map (f!([crumbs](t) Switch::new(crumbs.clone_ref(),*t))); - frp.source.on_port_hover <+ hover; + frp.output.on_port_hover <+ hover; // === Pointer Style === @@ -685,13 +694,13 @@ impl Area { init_color <- source::<()>(); any_type_sel_color <- all_with(&any_type_sel_color,&init_color, |c,_| color::Lcha::from(c)); - tp <- all_with(&port.tp,&frp.set_ports_active, + tp <- all_with(&port.tp,&frp.input.set_ports_active, |tp,(_,edge_tp)| tp.clone().or_else(||edge_tp.clone())); tp_color <- tp.map( f!([styles](tp) tp.map_ref(|tp| type_coloring::compute(tp,&styles)))); tp_color <- all_with(&tp_color,&any_type_sel_color, |tp_color,any_type_sel_color| tp_color.unwrap_or(*any_type_sel_color)); - in_profiling_mode <- frp.view_mode.map(|m| matches!(m,view::Mode::Profiling)); + in_profiling_mode <- frp.output.view_mode.map(|m| matches!(m,view::Mode::Profiling)); pointer_color_over <- in_profiling_mode.switch(&tp_color,&any_type_sel_color); pointer_style_over <- pointer_color_over.map(move |color| cursor::Style::new_highlight(&port_shape_hover,padded_size,Some(color)) @@ -701,10 +710,10 @@ impl Area { pointer_style_hover <- any(pointer_style_over,pointer_style_out); pointer_styles <- all[pointer_style_hover,self.model.label.pointer_style]; pointer_style <- pointer_styles.fold(); - self.frp.output.source.pointer_style <+ pointer_style; + self.frp.private.output.pointer_style <+ pointer_style; } init_color.emit(()); - frp.source.view_mode.emit(frp.view_mode.value()); + frp.output.view_mode.emit(frp.output.view_mode.value()); port_shape.display_object().clone_ref() }; @@ -725,6 +734,7 @@ impl Area { /// Initializes FRP network for every port. Please note that the networks are connected /// hierarchically (children get events from parents), so it is easier to init all networks /// this way, rather than delegate it to every port. + #[profile(Debug)] fn init_port_frp_on_new_expression(&self, expression: &mut Expression) { let model = &self.model; @@ -754,7 +764,7 @@ impl Area { ); frp.source.tp <+ final_tp; - self.frp.source.on_port_type_change <+ frp.tp.map(move |t|(crumbs.clone(),t.clone())); + self.frp.private.output.on_port_type_change <+ frp.tp.map(move |t|(crumbs.clone(),t.clone())); } @@ -864,7 +874,7 @@ impl Area { Some(frp.tp.clone_ref().into()) }); - self.frp.source.view_mode.emit(self.frp.view_mode.value()); + self.frp.private.output.view_mode.emit(self.frp.view_mode.value()); } /// This function first assigns the new expression to the model and then emits the definition @@ -875,6 +885,7 @@ impl Area { /// For example, firing the `port::set_definition_type` will fire `on_port_type_change`, which /// may require some edges to re-color, which consequently will require to checking the current /// expression types. + #[profile(Debug)] fn init_new_expression(&self, expression: Expression) { *self.model.expression.borrow_mut() = expression; let expression = self.model.expression.borrow(); @@ -883,6 +894,7 @@ impl Area { }); } + #[profile(Debug)] pub(crate) fn set_expression(&self, new_expression: impl Into) { let mut new_expression = Expression::from(new_expression.into()); if DEBUG { diff --git a/app/gui/view/graph-editor/src/component/node/input/port.rs b/app/gui/view/graph-editor/src/component/node/input/port.rs index 1ed0fec72a7..27afed55ce9 100644 --- a/app/gui/view/graph-editor/src/component/node/input/port.rs +++ b/app/gui/view/graph-editor/src/component/node/input/port.rs @@ -175,6 +175,7 @@ impl Model { /// as some are skipped. For example, given the expression `(((foo)))`, the inner parentheses /// will be skipped, as there is no point in making them ports. The skip algorithm is /// implemented as part of the port are initialization. + #[profile(Debug)] pub fn init_shape( &mut self, logger: impl AnyLogger, diff --git a/app/gui/view/graph-editor/src/component/node/output/area.rs b/app/gui/view/graph-editor/src/component/node/output/area.rs index 2d1551477ec..739993b3dc0 100644 --- a/app/gui/view/graph-editor/src/component/node/output/area.rs +++ b/app/gui/view/graph-editor/src/component/node/output/area.rs @@ -8,11 +8,13 @@ use crate::component::node::input; use crate::component::node::output::port; use crate::tooltip; use crate::view; +use crate::FrpNetworkProvider; use crate::Type; use enso_config::ARGS; use enso_frp as frp; use enso_frp; +use enso_frp::stream::ValueProvider; use ensogl::animation::hysteretic::HystereticAnimation; use ensogl::application::Application; use ensogl::data::color; @@ -120,7 +122,7 @@ impl From for Expression { // === Model === // ============= -ensogl::define_endpoints! { +ensogl::define_endpoints_2! { Input { set_size (Vector2), set_hover (bool), @@ -161,11 +163,12 @@ pub struct Model { port_count: Cell, styles: StyleWatch, styles_frp: StyleWatchFrp, - frp: FrpEndpoints, + frp: Rc, } impl Model { /// Constructor. + #[profile(Debug)] pub fn new(logger: impl AnyLogger, app: &Application, frp: &Frp) -> Self { let logger = Logger::new_sub(&logger, "output_ports"); let display_object = display::object::Instance::new(&logger); @@ -177,7 +180,7 @@ impl Model { let port_count = default(); let styles = StyleWatch::new(&app.display.default_scene.style_sheet); let styles_frp = StyleWatchFrp::new(&app.display.default_scene.style_sheet); - let frp = frp.output.clone_ref(); + let frp = frp.private.clone_ref(); display_object.add_child(&label); display_object.add_child(&ports); Self { @@ -196,6 +199,7 @@ impl Model { .init() } + #[profile(Debug)] fn init(self) -> Self { // FIXME[WD]: Depth sorting of labels to in front of the mouse pointer. Temporary solution. // It needs to be more flexible once we have proper depth management. @@ -228,10 +232,12 @@ impl Model { ports } + #[profile(Debug)] fn set_label_layer(&self, layer: &display::scene::Layer) { self.label.add_to_scene_layer(layer); } + #[profile(Debug)] fn set_label(&self, content: impl Into) { let str = if ARGS.node_labels.unwrap_or(true) { content.into() } else { default() }; self.label.set_content(str); @@ -239,6 +245,7 @@ impl Model { } /// Update expression type for the particular `ast::Id`. + #[profile(Debug)] fn set_expression_usage_type(&self, crumbs: &Crumbs, tp: &Option) { if let Ok(port) = self.expression.borrow().span_tree.root_ref().get_descendant(crumbs) { if let Some(frp) = &port.frp { @@ -249,6 +256,7 @@ impl Model { /// Traverse all span tree nodes that are considered ports. In case of empty span tree, include /// its root as the port as well. + #[profile(Debug)] fn traverse_borrowed_expression_mut( &self, mut f: impl FnMut(bool, &mut PortRefMut, &mut PortLayerBuilder), @@ -262,6 +270,7 @@ impl Model { /// Traverse all span tree nodes that are considered ports. In case of empty span tree, include /// its root as the port as well. + #[profile(Debug)] fn traverse_borrowed_expression( &self, mut f: impl FnMut(bool, &PortRef, &mut PortLayerBuilder), @@ -274,6 +283,7 @@ impl Model { } /// Traverse all span tree nodes that are considered ports. + #[profile(Debug)] fn traverse_borrowed_expression_raw_mut( &self, mut f: impl FnMut(bool, &mut PortRefMut, &mut PortLayerBuilder), @@ -293,6 +303,7 @@ impl Model { } /// Traverse all span tree nodes that are considered ports. + #[profile(Debug)] fn traverse_borrowed_expression_raw( &self, mut f: impl FnMut(bool, &PortRef, &mut PortLayerBuilder), @@ -318,6 +329,7 @@ impl Model { count } + #[profile(Debug)] fn set_size(&self, size: Vector2) { self.ports.set_position_x(size.x / 2.0); self.traverse_borrowed_expression_mut(|is_a_port, node, _| { @@ -327,10 +339,12 @@ impl Model { }) } + #[profile(Debug)] fn set_label_on_new_expression(&self, expression: &Expression) { self.set_label(expression.code()); } + #[profile(Debug)] fn build_port_shapes_on_new_expression(&self) { let mut port_index = 0; let mut id_crumbs_map = HashMap::new(); @@ -359,19 +373,19 @@ impl Model { let port_network = &port_frp.network; frp::extend! { port_network - self.frp.source.on_port_hover <+ port_frp.on_hover.map + self.frp.output.on_port_hover <+ port_frp.on_hover.map (f!([crumbs](t) Switch::new(crumbs.clone(),*t))); - self.frp.source.on_port_press <+ port_frp.on_press.constant(crumbs.clone()); + self.frp.output.on_port_press <+ port_frp.on_press.constant(crumbs.clone()); - port_frp.set_size_multiplier <+ self.frp.port_size_multiplier; - self.frp.source.on_port_type_change <+ port_frp.tp.map(move |t|(crumbs.clone(),t.clone())); - port_frp.set_type_label_visibility <+ self.frp.type_label_visibility; - self.frp.source.tooltip <+ port_frp.tooltip; - port_frp.set_view_mode <+ self.frp.view_mode; + port_frp.set_size_multiplier <+ self.frp.output.port_size_multiplier; + self.frp.output.on_port_type_change <+ port_frp.tp.map(move |t|(crumbs.clone(),t.clone())); + port_frp.set_type_label_visibility <+ self.frp.output.type_label_visibility; + self.frp.output.tooltip <+ port_frp.tooltip; + port_frp.set_view_mode <+ self.frp.output.view_mode; } - port_frp.set_type_label_visibility.emit(self.frp.type_label_visibility.value()); - port_frp.set_view_mode.emit(self.frp.view_mode.value()); + port_frp.set_type_label_visibility.emit(self.frp.output.type_label_visibility.value()); + port_frp.set_view_mode.emit(self.frp.output.view_mode.value()); self.ports.add_child(&port_shape); port_index += 1; } @@ -379,6 +393,7 @@ impl Model { *self.id_crumbs_map.borrow_mut() = id_crumbs_map; } + #[profile(Debug)] fn init_definition_types(&self) { let port_count = self.port_count.get(); let whole_expr_type = self.expression.borrow().whole_expr_type.clone(); @@ -399,6 +414,7 @@ impl Model { } } + #[profile(Debug)] fn set_expression(&self, new_expression: impl Into) { let new_expression = Expression::from(new_expression.into()); if DEBUG { @@ -452,7 +468,7 @@ impl Area { pub fn new(logger: impl AnyLogger, app: &Application) -> Self { let frp = Frp::new(); let model = Rc::new(Model::new(logger, app, &frp)); - let network = &frp.network; + let network = &frp.network(); let label_color = color::Animation::new(network); let hysteretic_transition = @@ -468,10 +484,10 @@ impl Area { hysteretic_transition.to_start <+ on_hover_in; hysteretic_transition.to_end <+ on_hover_out; - frp.source.port_size_multiplier <+ hysteretic_transition.value; + frp.private.output.port_size_multiplier <+ hysteretic_transition.value; eval frp.set_size ((t) model.set_size(*t)); - frp.source.type_label_visibility <+ frp.set_type_label_visibility; + frp.private.output.type_label_visibility <+ frp.set_type_label_visibility; // === Expression === @@ -482,12 +498,12 @@ impl Area { // === Label Color === - port_hover <- frp.on_port_hover.map(|t| t.is_on()); - frp.source.body_hover <+ frp.set_hover || port_hover; + port_hover <- frp.output.on_port_hover.map(|t| t.is_on()); + frp.private.output.body_hover <+ frp.set_hover || port_hover; expr_vis <- frp.body_hover || frp.set_expression_visibility; in_normal_mode <- frp.set_view_mode.map(|m| m.is_normal()); expr_vis <- expr_vis && in_normal_mode; - frp.source.expression_label_visibility <+ expr_vis; + frp.private.output.expression_label_visibility <+ expr_vis; let label_vis_color = color::Lcha::from(model.styles.get_color(theme::graph_editor::node::text)); let label_vis_alpha = label_vis_color.alpha; @@ -500,7 +516,7 @@ impl Area { // === View Mode === - frp.source.view_mode <+ frp.set_view_mode; + frp.private.output.view_mode <+ frp.set_view_mode; } label_color.target_alpha(0.0); diff --git a/app/ide-desktop/package-lock.json b/app/ide-desktop/package-lock.json index 85334637aca..36ba470926f 100644 --- a/app/ide-desktop/package-lock.json +++ b/app/ide-desktop/package-lock.json @@ -364,9 +364,9 @@ "integrity": "sha512-kbMawY0WRPyL/lbknBkme4CNLl+Gw+E9G4OpNeXAauqoQiNkBgpIvZYy7BRT4sNGhZbxdxXxXbruqUwDzLmvTw==" }, "node_modules/@firebase/analytics/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/app": { "version": "0.6.30", @@ -410,9 +410,9 @@ "integrity": "sha512-KJ+BqJbdNsx4QT/JIT1yDj5p6D+QN97iJs3GuHnORrqL+DU3RWc9nSYQsrY6Tv9jVWcOkMENXAgDT484vzsm2w==" }, "node_modules/@firebase/app-check/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/app-types": { "version": "0.6.3", @@ -420,9 +420,9 @@ "integrity": "sha512-/M13DPPati7FQHEQ9Minjk1HGLm/4K4gs9bR4rzLCWJg64yGtVC0zNg9gDpkw9yc2cvol/mNFxqTtd4geGrwdw==" }, "node_modules/@firebase/app/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/auth": { "version": "0.16.8", @@ -463,9 +463,9 @@ } }, "node_modules/@firebase/component/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/database": { "version": "0.11.0", @@ -502,9 +502,9 @@ } }, "node_modules/@firebase/database/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/firestore": { "version": "2.4.1", @@ -539,9 +539,9 @@ } }, "node_modules/@firebase/firestore/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/functions": { "version": "0.6.16", @@ -565,9 +565,9 @@ "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==" }, "node_modules/@firebase/functions/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/installations": { "version": "0.4.32", @@ -594,9 +594,9 @@ } }, "node_modules/@firebase/installations/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/logger": { "version": "0.2.6", @@ -629,9 +629,9 @@ } }, "node_modules/@firebase/messaging/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/performance": { "version": "0.4.18", @@ -656,9 +656,9 @@ "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==" }, "node_modules/@firebase/performance/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/polyfill": { "version": "0.3.36", @@ -693,9 +693,9 @@ "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" }, "node_modules/@firebase/remote-config/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/storage": { "version": "0.7.1", @@ -723,9 +723,9 @@ } }, "node_modules/@firebase/storage/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/util": { "version": "1.3.0", @@ -736,9 +736,9 @@ } }, "node_modules/@firebase/util/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/@firebase/webchannel-wrapper": { "version": "0.5.1", @@ -746,9 +746,9 @@ "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" }, "node_modules/@grpc/grpc-js": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.6.tgz", - "integrity": "sha512-gEMn1+d01yO/QNHsDOPHxJYtA6QItbdQT4mGFS8Gt5IQCq+83OEsD0sbvPf3RLCtHy1HI412JgQPr5HM9QK0mw==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.7.tgz", + "integrity": "sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw==", "dependencies": { "@grpc/proto-loader": "^0.6.4", "@types/node": ">=12.12.47" @@ -758,9 +758,9 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.9.tgz", - "integrity": "sha512-UlcCS8VbsU9d3XTXGiEVFonN7hXk+oMXZtoHHG2oSA1/GcDP1q6OUgs20PzHDGizzyi8ufGSUDlk3O2NyY7leg==", + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.12.tgz", + "integrity": "sha512-filTVbETFnxb9CyRX98zN18ilChTuf/C5scZ2xyaOTp0EHGq0/ufX8rjqXUcSb1Gpv7eZq4M2jDvbh9BogKnrg==", "dependencies": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", @@ -2454,9 +2454,9 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/minimatch": { "version": "3.0.3", @@ -2935,9 +2935,9 @@ "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==" }, "node_modules/app-builder-lib": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.0.6.tgz", - "integrity": "sha512-CmDyNldqqt7hMNV3EaHCPeml4iCqBZPXBOEq0M1j9KkBHPMXnQzoYECq2IQ3xv4PxADEqMeVAt/W2iAXBy4v5Q==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.0.8.tgz", + "integrity": "sha512-IObTdRc/0TQsfGn9IvaEXULE/QacgyFgpz3+vmlpZgHHjQ6V1c/T4pKlzNTsNHGjJBuEg2FvTvYi9ZVFfhyWow==", "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/universal": "1.2.1", @@ -2945,24 +2945,25 @@ "7zip-bin": "~5.1.1", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.2", - "ejs": "^3.1.6", + "debug": "^4.3.4", + "ejs": "^3.1.7", "electron-osx-sign": "^0.6.0", - "electron-publish": "23.0.6", + "electron-publish": "23.0.8", "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "hosted-git-info": "^4.0.2", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.8", + "isbinaryfile": "^4.0.10", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "read-config-file": "6.2.0", "sanitize-filename": "^1.6.3", - "semver": "^7.3.5", + "semver": "^7.3.7", + "tar": "^6.1.11", "temp-file": "^3.4.0" }, "engines": { @@ -4055,19 +4056,19 @@ } }, "node_modules/builder-util": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.0.6.tgz", - "integrity": "sha512-xV6JmZmHvpeUtsJNKDoKTefFLo9LRPnm4ii3ckRQe39BNu0nDyfpRLhici7KqnRxBdMSpIVIfayJX9syN+7zDw==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.0.8.tgz", + "integrity": "sha512-xPpnoLLAEPx5oxxzRFINRnxmLNQDn+FddU7QRvCJDQi0jvUJ7UjdoGoM+UPy9yh+p9O82/nC7MHGuUptJkOXyQ==", "dependencies": { "@types/debug": "^4.1.6", "@types/fs-extra": "^9.0.11", "7zip-bin": "~5.1.1", "app-builder-bin": "4.0.0", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.0.1", + "builder-util-runtime": "9.0.2", "chalk": "^4.1.1", "cross-spawn": "^7.0.3", - "debug": "^4.3.2", + "debug": "^4.3.4", "fs-extra": "^10.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -4079,11 +4080,11 @@ } }, "node_modules/builder-util-runtime": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.1.tgz", - "integrity": "sha512-f9pjsGKjGaLWqYwIn11Lxc2YL0g8UnnxWECOS9GubCRNYWnqMz1ZjwwCedOUKk2UlD2J7zyVKJcCMt9v/pP/uQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.2.tgz", + "integrity": "sha512-xF55W/8mgfT6+sMbX0TeiJkTusA5GMOzckM4rajN4KirFcUIuLTH8oEaTYmM86YwVCZaTwa/7GyFhauXaEICwA==", "dependencies": { - "debug": "^4.3.2", + "debug": "^4.3.4", "sax": "^1.2.4" }, "engines": { @@ -4533,9 +4534,9 @@ } }, "node_modules/camel-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/camelcase": { "version": "5.3.1", @@ -5022,9 +5023,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "node_modules/color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -6497,6 +6498,17 @@ "node": ">= 0.6.x" } }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/dir-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", @@ -6509,19 +6521,19 @@ } }, "node_modules/dmg-builder": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.0.6.tgz", - "integrity": "sha512-+2Wp3wDLAuj7qEBwqD9AssF68Uz3U0cwfvsz1qODKW1GBBEu/6X2LQUs4oDIdoIVpkai660+zyPok6f3DMfcSw==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.0.8.tgz", + "integrity": "sha512-dXguxjekxY70hzgAW+0NPCI7bagQ2ZrLDwYf1bvHSwlVfVizyJ/EC+e71U/NUgiWlXU5nogbWcGC3H74mFu0iw==", "dependencies": { - "app-builder-lib": "23.0.6", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "app-builder-lib": "23.0.8", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "fs-extra": "^10.0.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { - "dmg-license": "^1.0.9" + "dmg-license": "^1.0.11" } }, "node_modules/dmg-builder/node_modules/argparse": { @@ -6734,9 +6746,9 @@ } }, "node_modules/dot-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/dot-prop": { "version": "4.2.1", @@ -6809,11 +6821,11 @@ "dev": true }, "node_modules/ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", + "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", "dependencies": { - "jake": "^10.6.1" + "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" @@ -6840,16 +6852,16 @@ } }, "node_modules/electron-builder": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.0.6.tgz", - "integrity": "sha512-VA50mfjjsoEQ5DHwgT61CGua6F337phNYPumMXkcedfjpAS82H23H2hnu75E77m6zf0wRNGVj9o7Z3rYpwyXlg==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.0.8.tgz", + "integrity": "sha512-7WxdR4+l+VL4QN/K6NdqRQg7+cbIka4By1+4eN8odMPySSTI5d6nrV8R+SSRt9MXeWVdWlW8RCX5Pk6L0oaRug==", "dependencies": { "@types/yargs": "^17.0.1", - "app-builder-lib": "23.0.6", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "app-builder-lib": "23.0.8", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "chalk": "^4.1.1", - "dmg-builder": "23.0.6", + "dmg-builder": "23.0.8", "fs-extra": "^10.0.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", @@ -7176,13 +7188,13 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/electron-publish": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.0.6.tgz", - "integrity": "sha512-ikjgf93uHKyjfTIxVBs3jrDY3x2C06c7Vbq7QDMIQnvMWUqZd1mNTqWUBAr1IQfwX5xvapsWxAJ5TF/Ops5KLg==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.0.8.tgz", + "integrity": "sha512-GnqJH7Wh8LnapN4npl1Xs2Er/486/qxE3dV42WxXHX2VeoKAJTOuCzOVWCxpajaR3Msji4SkS0p81R018uK6Mg==", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "chalk": "^4.1.1", "fs-extra": "^10.0.0", "lazy-val": "^1.0.5", @@ -11350,9 +11362,9 @@ } }, "node_modules/lower-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/lowercase-keys": { "version": "1.0.1", @@ -11899,9 +11911,9 @@ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -12264,9 +12276,9 @@ } }, "node_modules/no-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/node-abi": { "version": "3.15.0", @@ -13287,9 +13299,9 @@ } }, "node_modules/param-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/parse-asn1": { "version": "5.1.6", @@ -13424,9 +13436,9 @@ } }, "node_modules/pascal-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/pascalcase": { "version": "0.1.1", @@ -16706,9 +16718,9 @@ } }, "node_modules/ts-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.3.0.tgz", - "integrity": "sha512-MgGly4I6cStsJy27ViE32UoqxPTN9Xly4anxxVyaIWR+9BGxboV4EyJBGfR3RePV7Ksjj3rHmPZJeIt+7o4Vag==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", + "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^4.0.0", @@ -19088,9 +19100,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19114,9 +19126,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19134,9 +19146,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19185,9 +19197,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19214,9 +19226,9 @@ } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19246,9 +19258,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19271,9 +19283,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19295,9 +19307,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19326,9 +19338,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19352,9 +19364,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19387,9 +19399,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19411,9 +19423,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19432,9 +19444,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -19444,18 +19456,18 @@ "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" }, "@grpc/grpc-js": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.6.tgz", - "integrity": "sha512-gEMn1+d01yO/QNHsDOPHxJYtA6QItbdQT4mGFS8Gt5IQCq+83OEsD0sbvPf3RLCtHy1HI412JgQPr5HM9QK0mw==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.7.tgz", + "integrity": "sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw==", "requires": { "@grpc/proto-loader": "^0.6.4", "@types/node": ">=12.12.47" } }, "@grpc/proto-loader": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.9.tgz", - "integrity": "sha512-UlcCS8VbsU9d3XTXGiEVFonN7hXk+oMXZtoHHG2oSA1/GcDP1q6OUgs20PzHDGizzyi8ufGSUDlk3O2NyY7leg==", + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.12.tgz", + "integrity": "sha512-filTVbETFnxb9CyRX98zN18ilChTuf/C5scZ2xyaOTp0EHGq0/ufX8rjqXUcSb1Gpv7eZq4M2jDvbh9BogKnrg==", "requires": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", @@ -20879,9 +20891,9 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, "@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "@types/minimatch": { "version": "3.0.3", @@ -21300,9 +21312,9 @@ "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==" }, "app-builder-lib": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.0.6.tgz", - "integrity": "sha512-CmDyNldqqt7hMNV3EaHCPeml4iCqBZPXBOEq0M1j9KkBHPMXnQzoYECq2IQ3xv4PxADEqMeVAt/W2iAXBy4v5Q==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.0.8.tgz", + "integrity": "sha512-IObTdRc/0TQsfGn9IvaEXULE/QacgyFgpz3+vmlpZgHHjQ6V1c/T4pKlzNTsNHGjJBuEg2FvTvYi9ZVFfhyWow==", "requires": { "@develar/schema-utils": "~2.6.5", "@electron/universal": "1.2.1", @@ -21310,24 +21322,25 @@ "7zip-bin": "~5.1.1", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.2", - "ejs": "^3.1.6", + "debug": "^4.3.4", + "ejs": "^3.1.7", "electron-osx-sign": "^0.6.0", - "electron-publish": "23.0.6", + "electron-publish": "23.0.8", "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "hosted-git-info": "^4.0.2", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.8", + "isbinaryfile": "^4.0.10", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "read-config-file": "6.2.0", "sanitize-filename": "^1.6.3", - "semver": "^7.3.5", + "semver": "^7.3.7", + "tar": "^6.1.11", "temp-file": "^3.4.0" }, "dependencies": { @@ -22193,19 +22206,19 @@ "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" }, "builder-util": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.0.6.tgz", - "integrity": "sha512-xV6JmZmHvpeUtsJNKDoKTefFLo9LRPnm4ii3ckRQe39BNu0nDyfpRLhici7KqnRxBdMSpIVIfayJX9syN+7zDw==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.0.8.tgz", + "integrity": "sha512-xPpnoLLAEPx5oxxzRFINRnxmLNQDn+FddU7QRvCJDQi0jvUJ7UjdoGoM+UPy9yh+p9O82/nC7MHGuUptJkOXyQ==", "requires": { "@types/debug": "^4.1.6", "@types/fs-extra": "^9.0.11", "7zip-bin": "~5.1.1", "app-builder-bin": "4.0.0", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.0.1", + "builder-util-runtime": "9.0.2", "chalk": "^4.1.1", "cross-spawn": "^7.0.3", - "debug": "^4.3.2", + "debug": "^4.3.4", "fs-extra": "^10.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -22383,11 +22396,11 @@ } }, "builder-util-runtime": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.1.tgz", - "integrity": "sha512-f9pjsGKjGaLWqYwIn11Lxc2YL0g8UnnxWECOS9GubCRNYWnqMz1ZjwwCedOUKk2UlD2J7zyVKJcCMt9v/pP/uQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.2.tgz", + "integrity": "sha512-xF55W/8mgfT6+sMbX0TeiJkTusA5GMOzckM4rajN4KirFcUIuLTH8oEaTYmM86YwVCZaTwa/7GyFhauXaEICwA==", "requires": { - "debug": "^4.3.2", + "debug": "^4.3.4", "sax": "^1.2.4" }, "dependencies": { @@ -22557,9 +22570,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -22957,9 +22970,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -24165,6 +24178,14 @@ "requires": { "graceful-readlink": ">= 1.0.0" } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } } } }, @@ -24177,14 +24198,14 @@ } }, "dmg-builder": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.0.6.tgz", - "integrity": "sha512-+2Wp3wDLAuj7qEBwqD9AssF68Uz3U0cwfvsz1qODKW1GBBEu/6X2LQUs4oDIdoIVpkai660+zyPok6f3DMfcSw==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.0.8.tgz", + "integrity": "sha512-dXguxjekxY70hzgAW+0NPCI7bagQ2ZrLDwYf1bvHSwlVfVizyJ/EC+e71U/NUgiWlXU5nogbWcGC3H74mFu0iw==", "requires": { - "app-builder-lib": "23.0.6", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", - "dmg-license": "^1.0.9", + "app-builder-lib": "23.0.8", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", + "dmg-license": "^1.0.11", "fs-extra": "^10.0.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -24348,9 +24369,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -24419,11 +24440,11 @@ "dev": true }, "ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", + "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", "requires": { - "jake": "^10.6.1" + "jake": "^10.8.5" } }, "electron": { @@ -24437,16 +24458,16 @@ } }, "electron-builder": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.0.6.tgz", - "integrity": "sha512-VA50mfjjsoEQ5DHwgT61CGua6F337phNYPumMXkcedfjpAS82H23H2hnu75E77m6zf0wRNGVj9o7Z3rYpwyXlg==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.0.8.tgz", + "integrity": "sha512-7WxdR4+l+VL4QN/K6NdqRQg7+cbIka4By1+4eN8odMPySSTI5d6nrV8R+SSRt9MXeWVdWlW8RCX5Pk6L0oaRug==", "requires": { "@types/yargs": "^17.0.1", - "app-builder-lib": "23.0.6", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "app-builder-lib": "23.0.8", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "chalk": "^4.1.1", - "dmg-builder": "23.0.6", + "dmg-builder": "23.0.8", "fs-extra": "^10.0.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", @@ -24690,13 +24711,13 @@ } }, "electron-publish": { - "version": "23.0.6", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.0.6.tgz", - "integrity": "sha512-ikjgf93uHKyjfTIxVBs3jrDY3x2C06c7Vbq7QDMIQnvMWUqZd1mNTqWUBAr1IQfwX5xvapsWxAJ5TF/Ops5KLg==", + "version": "23.0.8", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.0.8.tgz", + "integrity": "sha512-GnqJH7Wh8LnapN4npl1Xs2Er/486/qxE3dV42WxXHX2VeoKAJTOuCzOVWCxpajaR3Msji4SkS0p81R018uK6Mg==", "requires": { "@types/fs-extra": "^9.0.11", - "builder-util": "23.0.6", - "builder-util-runtime": "9.0.1", + "builder-util": "23.0.8", + "builder-util-runtime": "9.0.2", "chalk": "^4.1.1", "fs-extra": "^10.0.0", "lazy-val": "^1.0.5", @@ -27964,9 +27985,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -28386,9 +28407,9 @@ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -28700,9 +28721,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -29515,9 +29536,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -29638,9 +29659,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, @@ -32252,9 +32273,9 @@ } }, "ts-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.3.0.tgz", - "integrity": "sha512-MgGly4I6cStsJy27ViE32UoqxPTN9Xly4anxxVyaIWR+9BGxboV4EyJBGfR3RePV7Ksjj3rHmPZJeIt+7o4Vag==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", + "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", "requires": { "chalk": "^4.1.0", "enhanced-resolve": "^4.0.0", diff --git a/build/run.js b/build/run.js index 81adc7d07ba..9e28e765862 100755 --- a/build/run.js +++ b/build/run.js @@ -207,7 +207,7 @@ commands.build.rust = async function (argv) { console.log('Minimizing the WASM binary.') await gzip(paths.wasm.main, paths.wasm.mainGz) - const releaseLimitMb = 4.25 + const releaseLimitMb = 4.36 let limitMb = releaseLimitMb + allowExtraMb await checkWasmSize(paths.wasm.mainGz, limitMb) } diff --git a/lib/rust/ensogl/component/text/src/component/area.rs b/lib/rust/ensogl/component/text/src/component/area.rs index 092c7c869d1..5db945bced7 100644 --- a/lib/rust/ensogl/component/text/src/component/area.rs +++ b/lib/rust/ensogl/component/text/src/component/area.rs @@ -642,6 +642,7 @@ impl AreaModel { fn on_modified_selection(&self, _: &buffer::selection::Group, _: f32, _: bool) {} #[cfg(target_arch = "wasm32")] + #[profile(Debug)] fn on_modified_selection( &self, selections: &buffer::selection::Group, @@ -753,6 +754,7 @@ impl AreaModel { Location(line, column) } + #[profile(Debug)] fn init(self) -> Self { self.redraw(true); self @@ -1010,6 +1012,8 @@ impl AreaModel { selection.with_start(start).with_end(end) } + #[cfg(target_arch = "wasm32")] + #[profile(Debug)] #[cfg(target_arch = "wasm32")] fn set_font(&self, font_name: &str) { let app = &self.app; @@ -1143,3 +1147,22 @@ impl Drop for Area { self.remove_all_cursors(); } } + + + +#[cfg(test)] +mod tests { + use super::*; + + /// Assert that there is no inherent memory leak in the [text::Area]. + #[test] + fn assert_no_leak() { + let app = Application::new("root"); + let text = app.new_view::(); + let text_frp = Rc::downgrade(&text.frp); + let text_data = Rc::downgrade(&text.data); + drop(text); + assert_eq!(text_frp.strong_count(), 0, "There are FRP references left."); + assert_eq!(text_data.strong_count(), 0, "There are data references left."); + } +} diff --git a/lib/rust/ensogl/core/src/display/garbage.rs b/lib/rust/ensogl/core/src/display/garbage.rs index e1fabeec26b..16a3e0f6bc4 100644 --- a/lib/rust/ensogl/core/src/display/garbage.rs +++ b/lib/rust/ensogl/core/src/display/garbage.rs @@ -60,11 +60,13 @@ impl Collector { /// The collector is designed to handle EnsoGL component's FRP networks and models, but any /// structure with static timeline may be put. See [`Collector`] docs for information when /// the object will be finally dropped. + #[profile(Debug)] pub fn collect(&self, object: T) { self.garbage.borrow_mut().before_pixel_sync.push(Box::new(object)); } /// Pixel value requested (the points 1 and 2 in [`Collector`] docs). + #[profile(Debug)] pub fn pixel_synced(&self) { let mut garbage = self.garbage.borrow_mut(); let objects_being_moved = std::mem::take(&mut garbage.before_pixel_sync); @@ -72,6 +74,7 @@ impl Collector { } /// Pixel value retrieved (the point 3 in [`Collector`] docs). + #[profile(Debug)] pub fn pixel_updated(&self) { let mut garbage = self.garbage.borrow_mut(); let objects_being_moved = std::mem::take(&mut garbage.before_pixel_update); @@ -79,6 +82,7 @@ impl Collector { } /// Mouse events handled (the point 4 in [`Collector`] docs). + #[profile(Debug)] pub fn mouse_events_handled(&self) { let mut garbage = self.garbage.borrow_mut(); drop(std::mem::take(&mut garbage.before_mouse_events)); diff --git a/lib/rust/ensogl/core/src/display/shape/primitive/system.rs b/lib/rust/ensogl/core/src/display/shape/primitive/system.rs index bca6208c154..d5fef332c4a 100644 --- a/lib/rust/ensogl/core/src/display/shape/primitive/system.rs +++ b/lib/rust/ensogl/core/src/display/shape/primitive/system.rs @@ -459,6 +459,7 @@ macro_rules! _define_shape_system { type StaticShape = Shape; type System = ShapeSystem; + #[profile(Debug)] fn new(logger:impl AnyLogger) -> Self { let logger : Logger = Logger::new_sub(&logger,"dyn_shape"); let display_object = display::object::Instance::new(&logger); @@ -477,6 +478,7 @@ macro_rules! _define_shape_system { } impl display::shape::system::DynamicShapeInternals for DynamicShape { + #[profile(Debug)] fn add_instance(&self, shape:Shape) { self.display_object.add_child(&shape); self.params.size.add_attribute_binding(shape.sprite.size.clone_ref()); @@ -487,6 +489,7 @@ macro_rules! _define_shape_system { self.shapes.borrow_mut().push(shape); } + #[profile(Debug)] fn drop_instances(&self) { for shape in mem::take(&mut *self.shapes.borrow_mut()) { self.display_object.remove_child(&shape); @@ -539,6 +542,7 @@ macro_rules! _define_shape_system { std::any::TypeId::of::().into() } + #[profile(Debug)] fn new(scene:&display::scene::Scene) -> Self { let style_watch = display::shape::StyleWatch::new(&scene.style_sheet); let shape_def = Self::shape_def(&style_watch); @@ -568,6 +572,7 @@ macro_rules! _define_shape_system { impl display::shape::StaticShapeSystemInstance for ShapeSystem { type Shape = Shape; + #[profile(Debug)] fn new_instance(&self) -> Self::Shape { let sprite = self.shape_system.new_instance(); let id = sprite.instance_id; @@ -579,6 +584,7 @@ macro_rules! _define_shape_system { impl display::shape::DynShapeSystemInstance for ShapeSystem { type DynamicShape = DynamicShape; + #[profile(Debug)] fn instantiate(&self, dyn_shape:&Self::DynamicShape) -> symbol::GlobalInstanceId { let sprite = self.shape_system.new_instance(); let instance_id = sprite.instance_id; @@ -597,6 +603,7 @@ macro_rules! _define_shape_system { } impl ShapeSystem { + #[profile(Debug)] fn init_refresh_on_style_change(self) -> Self { let shape_system = self.shape_system.clone_ref(); let style_watch = self.style_watch.clone_ref(); @@ -607,6 +614,7 @@ macro_rules! _define_shape_system { } /// The canvas shape definition. + #[profile(Debug)] pub fn shape_def (__style_watch__:&display::shape::StyleWatch) -> display::shape::primitive::def::AnyShape { diff --git a/lib/rust/ensogl/core/src/display/world.rs b/lib/rust/ensogl/core/src/display/world.rs index 0ea3308790c..04b8462a228 100644 --- a/lib/rust/ensogl/core/src/display/world.rs +++ b/lib/rust/ensogl/core/src/display/world.rs @@ -300,6 +300,7 @@ impl WorldData { /// function is more precise than time obtained from the [`window.performance().now()`] one. /// Follow this link to learn more: /// https://stackoverflow.com/questions/38360250/requestanimationframe-now-vs-performance-now-time-discrepancy. + #[profile(Objective)] pub fn run_next_frame(&self, time: animation::TimeInfo) { let previous_frame_stats = self.stats.begin_frame(); if let Some(stats) = previous_frame_stats { @@ -319,6 +320,7 @@ impl WorldData { /// /// The collector is designed to handle EnsoGL component's FRP networks and models, but any /// structure with static timeline may be put. For details, see docs of [`garbage::Collector`]. + #[profile(Debug)] pub fn collect_garbage(&self, object: T) { self.garbage_collector.collect(object); } diff --git a/lib/rust/ensogl/core/src/gui/cursor.rs b/lib/rust/ensogl/core/src/gui/cursor.rs index 269052c1788..229dece587d 100644 --- a/lib/rust/ensogl/core/src/gui/cursor.rs +++ b/lib/rust/ensogl/core/src/gui/cursor.rs @@ -4,6 +4,7 @@ use crate::display::shape::*; use crate::gui::style::*; use crate::prelude::*; +use crate::application::command::FrpNetworkProvider; use crate::data::color; use crate::define_style; use crate::display; @@ -162,7 +163,7 @@ pub mod shape { // === Frp === // =========== -crate::define_endpoints! { +crate::define_endpoints_2! { Input { set_style (Style), } @@ -239,7 +240,7 @@ impl Cursor { /// Constructor. pub fn new(scene: &Scene) -> Self { let frp = Frp::new(); - let network = &frp.network; + let network = frp.network(); let model = CursorModel::new(scene); let mouse = &scene.mouse.frp; @@ -456,10 +457,10 @@ impl Cursor { // === Outputs === - frp.source.position <+ position; - frp.source.screen_position <+ screen_position; - frp.source.scene_position <+ scene_position; - frp.source.scene_position_delta <+ scene_position_delta; + frp.private.output.position <+ position; + frp.private.output.screen_position <+ screen_position; + frp.private.output.scene_position <+ scene_position; + frp.private.output.scene_position_delta <+ scene_position_delta; } // Hide on init. diff --git a/lib/rust/ensogl/example/profiling-run-graph/Cargo.toml b/lib/rust/ensogl/example/profiling-run-graph/Cargo.toml index f515040388a..31ce01c8dac 100644 --- a/lib/rust/ensogl/example/profiling-run-graph/Cargo.toml +++ b/lib/rust/ensogl/example/profiling-run-graph/Cargo.toml @@ -25,6 +25,8 @@ futures = "0.3" serde = "1" wasm-bindgen = { version = "0.2.58", features = [ "nightly" ] } wasm-bindgen-futures = "0.4" +url = "2.2.2" +qstring = "0.7.2" [dependencies.web-sys] version = "0.3" diff --git a/lib/rust/ensogl/example/profiling-run-graph/src/lib.rs b/lib/rust/ensogl/example/profiling-run-graph/src/lib.rs index 7e0493b8159..574a2b82337 100644 --- a/lib/rust/ensogl/example/profiling-run-graph/src/lib.rs +++ b/lib/rust/ensogl/example/profiling-run-graph/src/lib.rs @@ -1,7 +1,9 @@ //! Demo scene showing a sample flame graph. Can be used to display a log file, if you have one. -//! To do so, set the `PROFILER_LOG_NAME` to contain the profiling log name and it -//! will be used for rendering the visualisation. See the docs of `PROFILER_LOG_NAME` for more -//! information. +//! To do so, set a query parameter in the url to contain `file=` and it +//! will be used for rendering the visualisation. Note that the log file needs to be located in +//! the assets subdirectory that is served by the webserver, i.e. `enso/dist/content` or +//! `app/ide-desktop/lib/content/assets`. If no name is given a file named `profile.json` will +//! be loaded by default. If that file is not present, some dummy data will be displayed. // === Standard Linter Configuration === #![deny(non_ascii_idents)] @@ -50,16 +52,9 @@ use ensogl_sequence_diagram::SequenceDiagram; // === Constants === // ================= - - -/// Content of a profiler log, that will be rendered. If this is `None` some dummy data will be -/// generated and rendered. The file must be located in the assets subdirectory that is -/// served by the webserver, i.e. `enso/dist/content` or `app/ide-desktop/lib/content/assets`. -/// For example use `Some("profile.json")`. -const PROFILER_LOG_NAME: Option<&str> = Some("combined.json"); - -const SHOW_RPC_EVENT_MARKS: bool = false; -const SHOW_BACKEND_MESSAGE_MARKS: bool = false; +const DEFAULT_LOG_NAME: &str = "profile.json"; +const SHOW_RPC_EVENT_MARKS: bool = true; +const SHOW_BACKEND_MESSAGE_MARKS: bool = true; @@ -142,6 +137,30 @@ fn init_theme(scene: &Scene) { +mod js { + use super::*; + + #[wasm_bindgen(inline_js = " +export function get_url() { + return window.location.href +} + +")] + extern "C" { + #[allow(unsafe_code)] + pub fn get_url() -> String; + } +} + +fn get_target_file_from_url() -> Option { + let url = js::get_url(); + let url = url::Url::parse(&url).ok()?; + let query = url.query()?; + let query = qstring::QString::from(query); + query.get("file").map(|s| s.to_owned()) +} + + // =========================== // === Metadata Processing === // =========================== @@ -204,11 +223,13 @@ fn make_rendering_performance_blocks( // === Profiler Log Reading === // ============================ -/// Read the `PROFILER_LOG_NAME` data from a file. +/// Read the log file data from a file, if one is specified. async fn get_data_raw() -> Option { use wasm_bindgen::JsCast; - let url = &["assets/", PROFILER_LOG_NAME?].concat(); + let file_name = get_target_file_from_url(); + let file_name = file_name.as_deref().unwrap_or(DEFAULT_LOG_NAME); + let url = &["assets/", file_name].concat(); let mut opts = web_sys::RequestInit::new(); opts.method("GET"); opts.mode(web_sys::RequestMode::Cors); diff --git a/lib/rust/ensogl/example/render-profile-flamegraph/Cargo.toml b/lib/rust/ensogl/example/render-profile-flamegraph/Cargo.toml index 2ed17fde74d..8dda03bc7d9 100644 --- a/lib/rust/ensogl/example/render-profile-flamegraph/Cargo.toml +++ b/lib/rust/ensogl/example/render-profile-flamegraph/Cargo.toml @@ -19,10 +19,12 @@ ensogl-flame-graph = { path = "../../component/flame-graph" } ensogl-hardcoded-theme = { path = "../../app/theme/hardcoded" } ensogl-text = { path = "../../component/text" } ensogl-text-msdf-sys = { path = "../../component/text/msdf-sys" } +ensogl-tooltip = { path = "../../component/tooltip" } futures = "0.3" wasm-bindgen = { version = "0.2.58", features = [ "nightly" ] } wasm-bindgen-futures = "0.4" + [dependencies.web-sys] version = "0.3" features = [ diff --git a/lib/rust/ensogl/example/render-profile-flamegraph/src/lib.rs b/lib/rust/ensogl/example/render-profile-flamegraph/src/lib.rs index d9aa79ef70a..8dce6f8a1cd 100644 --- a/lib/rust/ensogl/example/render-profile-flamegraph/src/lib.rs +++ b/lib/rust/ensogl/example/render-profile-flamegraph/src/lib.rs @@ -18,10 +18,13 @@ use wasm_bindgen::prelude::*; use enso_profiler_data as profiler_data; use enso_profiler_flame_graph as profiler_flame_graph; use ensogl_core::application; +use ensogl_core::application::command::FrpNetworkProvider; +use ensogl_core::application::tooltip::Placement; use ensogl_core::data::color; use ensogl_core::display; use ensogl_core::display::navigation::navigator; use ensogl_core::display::style::theme; +use ensogl_core::frp; use ensogl_flame_graph as flame_graph; @@ -35,25 +38,33 @@ use ensogl_flame_graph as flame_graph; #[allow(dead_code)] pub async fn entry_point_render_profile_flamegraph() { use ensogl_core::display::object::ObjectOps; - let app = application::Application::new("root"); + let app = &application::Application::new("root"); let world = &app.display; let scene = &world.default_scene; + let network = app.frp.network(); let navigator = navigator::Navigator::new(scene, &scene.camera()); init_theme(scene); let data = get_data().await; let profile: profiler_data::Profile = data.parse().unwrap(); let mut builder = profiler_flame_graph::FlamegraphBuilder::default(); builder.add_profile(&profile); - let flame_graph = flame_graph::FlameGraph::from_data(builder.into(), &app); + let flame_graph = flame_graph::FlameGraph::from_data(builder.into(), app); scene.add_child(&flame_graph); scene.layers.main.add_exclusive(&flame_graph); world.keep_alive_forever(); + let tooltip = ensogl_tooltip::Tooltip::new(app); + scene.add_child(&tooltip); + tooltip.frp.set_placement.emit(Placement::Right); + frp::extend! { network + tooltip.frp.set_style <+ app.frp.tooltip.map(|tt| tt.clone().with_placement(Placement::Right)); + } world .on .before_frame .add(move |_time| { let _keep_alive = &navigator; let _keep_alive = &flame_graph; + let _keep_alive = &tooltip; }) .forget(); } @@ -67,7 +78,7 @@ pub async fn entry_point_render_profile_flamegraph() { async fn get_data() -> String { use wasm_bindgen::JsCast; - let url = "/profile.json"; + let url = "assets/profile.json"; let mut opts = web_sys::RequestInit::new(); opts.method("GET"); opts.mode(web_sys::RequestMode::Cors); @@ -88,6 +99,7 @@ fn init_theme(scene: &display::Scene) { let theme = theme::Theme::new(); const COLOR_PATH: &str = "flame_graph_color"; theme.set(COLOR_PATH, color::Rgb::new(1.0, 45.0 / 255.0, 0.0)); + theme.set("component.label.text", color::Lcha::black()); theme_manager.register("theme", theme); theme_manager.set_enabled(&["theme".to_string()]); let style_watch = ensogl_core::display::shape::StyleWatch::new(&scene.style_sheet); diff --git a/lib/rust/frp/src/stream.rs b/lib/rust/frp/src/stream.rs index 6fced387a56..f05cdd259bf 100644 --- a/lib/rust/frp/src/stream.rs +++ b/lib/rust/frp/src/stream.rs @@ -306,7 +306,7 @@ impl EventEmitter for NodeData { impl ValueProvider for NodeData { fn value(&self) -> Out { if !self.use_caching() { - panic!("Trying to read not cached value.") + Out::default(); } self.value_cache.borrow().clone() } diff --git a/lib/rust/profiler/data/src/bin/intervals.rs b/lib/rust/profiler/data/src/bin/intervals.rs index ee717e7eef9..11a20d02516 100644 --- a/lib/rust/profiler/data/src/bin/intervals.rs +++ b/lib/rust/profiler/data/src/bin/intervals.rs @@ -33,7 +33,6 @@ use enso_profiler_data as data; use std::collections; - // ============ // === main === // ============ diff --git a/lib/rust/profiler/data/src/parse.rs b/lib/rust/profiler/data/src/parse.rs index 2980383e4df..b8a277a6463 100644 --- a/lib/rust/profiler/data/src/parse.rs +++ b/lib/rust/profiler/data/src/parse.rs @@ -285,7 +285,7 @@ impl LogVisitor { format::Event::Pause { id, timestamp } => visitor.visit_pause(log_pos, id, timestamp), format::Event::Metadata(metadata) => visitor.visit_metadata(log_pos, metadata), - format::Event::Label { label } => visitor.visit_label(log_pos, label), + format::Event::Label { label } => visitor.visit_label(log_pos, label.as_ref()), }; result.map_err(|error| crate::EventError { log_pos: i, error })?; event_count += 1; diff --git a/lib/rust/profiler/flame-graph/src/lib.rs b/lib/rust/profiler/flame-graph/src/lib.rs index 95d3524eba7..4e0884e5282 100644 --- a/lib/rust/profiler/flame-graph/src/lib.rs +++ b/lib/rust/profiler/flame-graph/src/lib.rs @@ -18,6 +18,13 @@ use enso_profiler_data as data; type RowNumber = i32; +// ======================= +// === Label Formating === +// ======================= + +fn with_timing_info(base: &str, [t1, t2]: [f64; 2]) -> String { + format!("{}\n[{:.2},{:.2}]", base, t1, t2) +} // ================== // === Block Data === @@ -167,6 +174,7 @@ impl<'p, Metadata> CallgraphBuilder<'p, Metadata> { return; } let label = self.profile[active.measurement].label.to_string(); + let label = with_timing_info(&label, [start, end]); self.blocks.push(Block { start, end, label, row, block_type: Activity::Active }); for child in &active.children { self.visit_interval(*child, row + 1); @@ -228,9 +236,13 @@ impl<'p, Metadata> RungraphBuilder<'p, Metadata> { let active_interval = [current_start, current_end]; let sleep_interval = [current_end, next_start]; + let label_active = self.profile[current.measurement].label.to_string(); + let label_active = with_timing_info(&label_active, active_interval); let label_sleep = format!("{} (inactive)", self.profile[current.measurement].label); + let label_sleep = with_timing_info(&label_sleep, sleep_interval); + self.blocks.push(Block { start: active_interval[0], @@ -253,10 +265,15 @@ impl<'p, Metadata> RungraphBuilder<'p, Metadata> { // Add first inactive interval. let first = measurement.intervals.first().unwrap(); // There are at least two intervals. let first = &self.profile[*first]; + let inactive_interval = [measurement.created.into_ms(), first.interval.start.into_ms()]; + let label = with_timing_info( + &self.profile[first.measurement].label.to_string(), + inactive_interval, + ); self.blocks.push(Block { - start: measurement.created.into_ms(), - end: first.interval.start.into_ms(), - label: self.profile[first.measurement].label.to_string(), + start: inactive_interval[0], + end: inactive_interval[1], + label, row, block_type: Activity::Paused, }); @@ -264,10 +281,18 @@ impl<'p, Metadata> RungraphBuilder<'p, Metadata> { // Add last active interval. let last = measurement.intervals.last().unwrap(); // There are at least two intervals. let last = &self.profile[*last]; + let active_interval = [ + last.interval.start.into_ms(), + last.interval.end.map(|end| end.into_ms()).unwrap_or(f64::INFINITY), + ]; + let label = with_timing_info( + &self.profile[last.measurement].label.to_string(), + active_interval, + ); self.blocks.push(Block { - start: last.interval.start.into_ms(), - end: last.interval.end.map(|end| end.into_ms()).unwrap_or(f64::INFINITY), - label: self.profile[last.measurement].label.to_string(), + start: active_interval[0], + end: active_interval[1], + label, row, block_type: Activity::Active, }); diff --git a/lib/rust/profiler/src/format.rs b/lib/rust/profiler/src/format.rs index f6ca8627e8b..62d827012a4 100644 --- a/lib/rust/profiler/src/format.rs +++ b/lib/rust/profiler/src/format.rs @@ -5,6 +5,7 @@ use serde; use serde::Deserialize; use serde::Serialize; +use std::borrow::Cow; // ============== @@ -32,9 +33,10 @@ pub enum Event<'a> { /// Registers a label to be referenced by ID. #[serde(rename = "L")] Label { - /// The text content of the label. + /// The text content of the label. Might need to be an owned string, if the original data + /// contains an escape sequence. #[serde(rename = "l")] - label: &'a str, + label: Cow<'a, str>, }, /// The beginning of a measurement that starts in the paused state. #[serde(rename = "C")] @@ -298,4 +300,13 @@ mod tests { // re-serializing the data structures produces the same blob as the input. assert_eq!(LOG, serde_json::to_string(&events).unwrap()); } + + /// Verify that the current implementation can deserialize escaped paths in the json file. + #[test] + fn escaped_json() { + // Example data containing a string with escaped characters. + const LOG: &str = r#"[{"L":{"l":"entry_point_ide (app\\ui\\src\\lib.rs:134)"}}]"#; + // Check that we can deserialize the data. + let _events: Vec = serde_json::from_str(LOG).unwrap(); + } } diff --git a/lib/rust/profiler/src/format/builder.rs b/lib/rust/profiler/src/format/builder.rs index 4c3fe13a429..e41eb8a9459 100644 --- a/lib/rust/profiler/src/format/builder.rs +++ b/lib/rust/profiler/src/format/builder.rs @@ -43,6 +43,7 @@ impl<'a> Builder<'a> { // Get or register label. let next_label_id = self.labels.len(); let label = *self.labels.entry(label).or_insert_with(|| { + let label = label.into(); self.events.push(format::Event::Label { label }); format::Label(next_label_id) });