mirror of
https://github.com/enso-org/enso.git
synced 2024-11-23 08:08:34 +03:00
Optimize opening dropdown (#5688)
* Profiling * Defer rendering hidden Text
This commit is contained in:
parent
afb853a03f
commit
2acc61d0b1
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2492,6 +2492,7 @@ dependencies = [
|
||||
"enso-executor",
|
||||
"enso-notification",
|
||||
"enso-prelude",
|
||||
"enso-profiler",
|
||||
"enso-text",
|
||||
"failure",
|
||||
"flo_stream",
|
||||
@ -2832,6 +2833,7 @@ dependencies = [
|
||||
name = "ensogl-example-render-profile-flamegraph"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"enso-debug-api",
|
||||
"enso-frp",
|
||||
"enso-profiler-data",
|
||||
"enso-profiler-demo-data",
|
||||
|
@ -38,8 +38,6 @@ impl From<JsValue> for Error {
|
||||
|
||||
#[wasm_bindgen(module = "/pkg/scala-parser.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
fn doc_parser_generate_html_source(content: String) -> std::result::Result<String, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
fn doc_parser_generate_html_from_doc(content: String) -> std::result::Result<String, JsValue>;
|
||||
}
|
||||
@ -56,16 +54,8 @@ impl Client {
|
||||
Ok(Client {})
|
||||
}
|
||||
|
||||
/// Calls JS doc parser to generate HTML from documented Enso code.
|
||||
pub fn generate_html_docs(&self, program: String) -> api::Result<String> {
|
||||
let html_code = || {
|
||||
let html_code = doc_parser_generate_html_source(program)?;
|
||||
Result::Ok(html_code)
|
||||
};
|
||||
Ok(html_code()?)
|
||||
}
|
||||
|
||||
/// Calls JS doc parser to generate HTML from pure doc code without Enso's AST.
|
||||
#[profile(Detail)]
|
||||
pub fn generate_html_doc_pure(&self, code: String) -> api::Result<String> {
|
||||
let html_code = || {
|
||||
let html_code = doc_parser_generate_html_from_doc(code)?;
|
||||
|
@ -82,12 +82,6 @@ impl DocParser {
|
||||
DocParser::new().unwrap_or_else(|e| panic!("Failed to create doc parser: {e:?}"))
|
||||
}
|
||||
|
||||
/// Parses program with documentation and generates HTML code.
|
||||
/// If the program does not have any documentation will return empty string.
|
||||
pub fn generate_html_docs(&self, program: String) -> api::Result<String> {
|
||||
self.borrow_mut().generate_html_docs(program)
|
||||
}
|
||||
|
||||
/// Parses pure documentation code and generates HTML code.
|
||||
/// Will return empty string for empty entry.
|
||||
pub fn generate_html_doc_pure(&self, code: String) -> api::Result<String> {
|
||||
|
@ -88,7 +88,6 @@ impl From<serde_json::error::Error> for Error {
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Request {
|
||||
DocParserGenerateHtmlSource { program: String },
|
||||
DocParserGenerateHtmlFromDoc { code: String },
|
||||
}
|
||||
|
||||
@ -196,17 +195,8 @@ impl Client {
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
/// Sends a request to parser service to generate HTML code from documented Enso code.
|
||||
pub fn generate_html_docs(&mut self, program: String) -> api::Result<String> {
|
||||
let request = Request::DocParserGenerateHtmlSource { program };
|
||||
let response_doc = self.rpc_call_doc(request)?;
|
||||
match response_doc {
|
||||
ResponseDoc::SuccessDoc { code } => Ok(code),
|
||||
ResponseDoc::Error { message } => Err(ParsingError(message)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends a request to parser service to generate HTML code from pure documentation code.
|
||||
#[profile(Detail)]
|
||||
pub fn generate_html_doc_pure(&mut self, code: String) -> api::Result<String> {
|
||||
let request = Request::DocParserGenerateHtmlFromDoc { code };
|
||||
let response_doc = self.rpc_call_doc(request)?;
|
||||
|
@ -14,6 +14,7 @@ span-tree = { path = "../language/span-tree" }
|
||||
ast = { path = "../language/ast/impl" }
|
||||
parser = { path = "../language/parser" }
|
||||
parser-scala = { path = "../language/parser-scala" }
|
||||
enso-profiler = { path = "../../../lib/rust/profiler" }
|
||||
enso-text = { path = "../../../lib/rust/text" }
|
||||
double-representation = { path = "../controller/double-representation" }
|
||||
engine-protocol = { path = "../controller/engine-protocol" }
|
||||
|
@ -43,6 +43,8 @@ use engine_protocol::language_server;
|
||||
use engine_protocol::language_server::SuggestionId;
|
||||
use enso_data_structures::hash_map_tree::HashMapTree;
|
||||
use enso_notification as notification;
|
||||
use enso_profiler as profiler;
|
||||
use enso_profiler::prelude::*;
|
||||
use flo_stream::Subscriber;
|
||||
use language_server::types::SuggestionDatabaseUpdatesEvent;
|
||||
use language_server::types::SuggestionsDatabaseVersion;
|
||||
@ -412,6 +414,7 @@ impl SuggestionDatabase {
|
||||
}
|
||||
|
||||
/// Apply the update event to the database.
|
||||
#[profile(Detail)]
|
||||
pub fn apply_update_event(&self, event: SuggestionDatabaseUpdatesEvent) {
|
||||
for update in event.updates {
|
||||
let mut entries = self.entries.borrow_mut();
|
||||
|
@ -103,6 +103,7 @@ pub struct View {
|
||||
impl View {
|
||||
/// Create a new node widget. The widget is initialized to empty state, waiting for widget
|
||||
/// metadata to be provided using `set_node_data` and `set_metadata` FRP endpoints.
|
||||
#[profile(Task)]
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let frp = Frp::new();
|
||||
let model = Rc::new(Model::new(app));
|
||||
@ -160,6 +161,7 @@ impl Model {
|
||||
Self { app, display_object, kind_model: kind }
|
||||
}
|
||||
|
||||
#[profile(Task)]
|
||||
fn set_widget_data(&self, frp: &SampledFrp, meta: &Option<Metadata>, node_data: &NodeData) {
|
||||
trace!("Setting widget data: {:?} {:?}", meta, node_data);
|
||||
|
||||
@ -426,6 +428,7 @@ impl LazyDropdown {
|
||||
}
|
||||
}
|
||||
|
||||
#[profile(Detail)]
|
||||
fn initialize_on_open(&mut self) {
|
||||
match self {
|
||||
LazyDropdown::Initialized(..) => {}
|
||||
|
@ -2130,6 +2130,7 @@ impl GraphEditorModel {
|
||||
}
|
||||
}
|
||||
|
||||
#[profile(Debug)]
|
||||
fn set_node_expression_usage_type(
|
||||
&self,
|
||||
node_id: impl Into<NodeId>,
|
||||
|
@ -86,6 +86,9 @@ pub struct EntryData {
|
||||
display_object: display::object::Instance,
|
||||
label_thin: text::Text,
|
||||
label_bold: text::Text,
|
||||
selected: Cell<bool>,
|
||||
/// A text change to the currently-hidden label that has not yet been applied.
|
||||
deferred_label: RefCell<Option<ImString>>,
|
||||
}
|
||||
|
||||
impl EntryData {
|
||||
@ -101,16 +104,28 @@ impl EntryData {
|
||||
label_thin.add_to_scene_layer(layer);
|
||||
label_bold.add_to_scene_layer(layer);
|
||||
}
|
||||
Self { display_object, label_thin, label_bold }
|
||||
let selected = default();
|
||||
let deferred_label = default();
|
||||
Self { display_object, label_thin, label_bold, selected, deferred_label }
|
||||
}
|
||||
|
||||
fn update_selected(&self, selected: bool) {
|
||||
if selected {
|
||||
self.display_object.remove_child(&self.label_thin);
|
||||
self.display_object.add_child(&self.label_bold);
|
||||
} else {
|
||||
self.display_object.remove_child(&self.label_bold);
|
||||
self.display_object.add_child(&self.label_thin);
|
||||
let was_selected = self.selected.replace(selected);
|
||||
if selected != was_selected {
|
||||
let new = self.selected_label();
|
||||
if let Some(label) = self.deferred_label.take() {
|
||||
new.set_content(label);
|
||||
}
|
||||
self.display_object.remove_all_children();
|
||||
self.display_object.add_child(new);
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the currently-enabled text control.
|
||||
fn selected_label(&self) -> &text::Text {
|
||||
match self.selected.get() {
|
||||
true => &self.label_bold,
|
||||
false => &self.label_thin,
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,6 +134,11 @@ impl EntryData {
|
||||
self.label_thin.set_xy(label_pos);
|
||||
self.label_bold.set_xy(label_pos);
|
||||
}
|
||||
|
||||
fn set_content(&self, text: &ImString) {
|
||||
self.selected_label().set_content(text.clone_ref());
|
||||
self.deferred_label.set(text.clone_ref());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -135,6 +155,7 @@ impl ensogl_grid_view::Entry for Entry {
|
||||
type Model = EntryModel;
|
||||
type Params = EntryParams;
|
||||
|
||||
#[profile(Debug)]
|
||||
fn new(app: &Application, text_layer: Option<&Layer>) -> Self {
|
||||
let data = Rc::new(EntryData::new(app, text_layer));
|
||||
let frp = EntryFrp::<Self>::new();
|
||||
@ -160,8 +181,6 @@ impl ensogl_grid_view::Entry for Entry {
|
||||
);
|
||||
layout <- all(contour, text_size, text_offset);
|
||||
eval layout ((&(c, ts, to)) data.update_layout(c, ts, to));
|
||||
selected <- input.set_model.map(|m| *m.selected);
|
||||
eval selected ((&s) data.update_selected(s));
|
||||
|
||||
text_size <- text_size.ref_into_some();
|
||||
data.label_thin.set_property_default <+ text_size;
|
||||
@ -171,7 +190,10 @@ impl ensogl_grid_view::Entry for Entry {
|
||||
data.label_thin.set_font <+ font;
|
||||
data.label_bold.set_font <+ font;
|
||||
|
||||
desired_entry_width <- data.label_bold.width.map2(&text_offset, |w, offset| w + offset);
|
||||
bold_width <- data.label_bold.width.map2(&text_offset, |w, offset| w + offset);
|
||||
thin_width <- data.label_thin.width.map2(&text_offset, |w, offset| w + offset);
|
||||
widths <- all(bold_width, thin_width);
|
||||
desired_entry_width <- widths.map(|&(b, t)| b.max(t)).on_change();
|
||||
limited_entry_width <- desired_entry_width.map2(&input.set_params, |width, params| {
|
||||
// Using min/max to avoid a panic in clamp when min_width > max_width. In those
|
||||
// cases, the max value is returned instead.
|
||||
@ -184,9 +206,10 @@ impl ensogl_grid_view::Entry for Entry {
|
||||
data.label_thin.set_view_width <+ view_width;
|
||||
data.label_bold.set_view_width <+ view_width;
|
||||
|
||||
content <- input.set_model.map(|m| m.text.clone_ref());;
|
||||
data.label_thin.set_content <+ content;
|
||||
data.label_bold.set_content <+ content;
|
||||
eval input.set_model ((m) {
|
||||
data.update_selected(*m.selected);
|
||||
data.set_content(&m.text);
|
||||
});
|
||||
|
||||
out.contour <+ contour;
|
||||
out.highlight_contour <+ contour;
|
||||
|
@ -142,6 +142,7 @@ ensogl_core::define_endpoints_2! { <T: (DropdownValue)>
|
||||
}
|
||||
|
||||
impl<T: DropdownValue> Frp<T> {
|
||||
#[profile(Debug)]
|
||||
fn init(network: &frp::Network, api: &api::Private<T>, model: &Model<T>) {
|
||||
let input = &api.input;
|
||||
let output = &api.output;
|
||||
|
@ -76,6 +76,7 @@ impl<T> component::Model for Model<T> {
|
||||
"Dropdown"
|
||||
}
|
||||
|
||||
#[profile(Debug)]
|
||||
fn new(app: &Application) -> Self {
|
||||
let display_object = display::object::Instance::new();
|
||||
|
||||
@ -97,6 +98,7 @@ impl<T> component::Model for Model<T> {
|
||||
|
||||
impl<T: DropdownValue> Model<T> {
|
||||
/// Set the minimum and maximum allowed inner width of an entry.
|
||||
#[profile(Debug)]
|
||||
pub fn set_outer_width_bounds(&self, min_outer_width: f32, max_outer_width: f32) {
|
||||
let corners_radius = CORNER_RADIUS - CLIP_PADDING;
|
||||
let max_width = max_outer_width - CLIP_PADDING * 2.0;
|
||||
@ -107,6 +109,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
}
|
||||
|
||||
/// Set the dimensions of all ui elements of the dropdown.
|
||||
#[profile(Debug)]
|
||||
pub fn set_dimensions(
|
||||
&self,
|
||||
num_entries: usize,
|
||||
@ -136,6 +139,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
self.grid.resize_grid(num_entries, 1);
|
||||
}
|
||||
|
||||
#[profile(Debug)]
|
||||
pub fn set_selection(&self, selected: &HashSet<T>, allow_multiselect: bool) {
|
||||
let mut entries = self.selected_entries.borrow_mut();
|
||||
entries.clear();
|
||||
@ -148,6 +152,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
|
||||
/// Convert provided list of indices onto sets of index ranges. One set of ranges is for indices
|
||||
/// that are already in cache, and the other set is for indices that need to be requested.
|
||||
#[profile(Debug)]
|
||||
pub fn get_ready_and_request_ranges(
|
||||
&self,
|
||||
requested_indices: &[usize],
|
||||
@ -180,6 +185,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
/// Accepts entry at given index, modifying selection. If entry is already selected, it will be
|
||||
/// unselected, unless it is the last selected entry and `allow_empty` is false. For
|
||||
/// single-select dropdowns, previously selected entry will be unselected.
|
||||
#[profile(Debug)]
|
||||
pub fn accept_entry_at_index(&self, index: usize, allow_multiselect: bool, allow_empty: bool) {
|
||||
let cache = self.cache.borrow();
|
||||
let Some(entry) = cache.get(index) else { return };
|
||||
@ -201,6 +207,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
///
|
||||
/// Note: The iterator borrows cache and selection. Make sure to drop it before calling any
|
||||
/// methods that need to borrow them mutably.
|
||||
#[profile(Debug)]
|
||||
pub fn entry_models_for_range(
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
@ -216,6 +223,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
}
|
||||
|
||||
/// Update cache with new entries at given range. Returns range of indices that were updated.
|
||||
#[profile(Debug)]
|
||||
pub fn insert_entries_in_range(
|
||||
&self,
|
||||
updated_range: Range<usize>,
|
||||
@ -236,6 +244,7 @@ impl<T: DropdownValue> Model<T> {
|
||||
|
||||
/// Prune selection according to changed multiselect mode. Returns true if the selection was
|
||||
/// changed.
|
||||
#[profile(Debug)]
|
||||
pub fn set_multiselect(&self, multiselect: bool) -> bool {
|
||||
let mut entries = self.selected_entries.borrow_mut();
|
||||
if !multiselect && entries.len() > 1 {
|
||||
|
@ -316,6 +316,7 @@ impl<Entry: entry::Entry, EntryParams> Model<Entry, EntryParams> {
|
||||
}
|
||||
|
||||
impl<E: Entry> Model<E, E::Params> {
|
||||
#[profile(Debug)]
|
||||
fn update_entry(
|
||||
&self,
|
||||
row: Row,
|
||||
|
@ -1020,6 +1020,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Recompute the shape of the provided line index.
|
||||
#[profile(Debug)]
|
||||
pub fn shape_line(&self, line: Line) -> ShapedLine {
|
||||
let line_range = self.line_range_snapped(line);
|
||||
let glyph_sets = self.shape_range(line_range.clone());
|
||||
@ -1116,6 +1117,7 @@ impl TextModel {
|
||||
/// and to the right of the insertion point. Unfortunately, the current Rustybuzz
|
||||
/// implementation does not support such use cases:
|
||||
/// https://github.com/RazrFalcon/rustybuzz/issues/54
|
||||
#[profile(Debug)]
|
||||
fn update_lines_after_change(&self, changes: Option<&[buffer::Change]>) {
|
||||
debug_span!("update_lines_after_change").in_scope(|| {
|
||||
self.detach_glyphs_from_cursors();
|
||||
@ -1193,6 +1195,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Replace selections with new ones.
|
||||
#[profile(Debug)]
|
||||
fn replace_selections(&self, do_edit: bool, buffer_selections: &buffer::selection::Group) {
|
||||
let mut new_selection_map = SelectionMap::default();
|
||||
for buffer_selection in buffer_selections {
|
||||
@ -1278,6 +1281,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Redraw the given line ranges.
|
||||
#[profile(Debug)]
|
||||
fn redraw_sorted_line_ranges(
|
||||
&self,
|
||||
sorted_line_ranges: impl Iterator<Item = RangeInclusive<ViewLine>>,
|
||||
@ -1293,6 +1297,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Redraw the line. This will re-position all line glyphs.
|
||||
#[profile(Debug)]
|
||||
fn redraw_line(&self, view_line: ViewLine) {
|
||||
let line = &mut self.lines.borrow_mut()[view_line];
|
||||
let default_divs = || NonEmptyVec::singleton(0.0);
|
||||
@ -1439,6 +1444,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Attach glyphs to cursors if cursors are in edit mode.
|
||||
#[profile(Debug)]
|
||||
pub fn attach_glyphs_to_cursors(&self) {
|
||||
for line in ViewLine(0)..=self.buffer.last_view_line_index() {
|
||||
self.attach_glyphs_to_cursors_for_line(line)
|
||||
@ -1486,6 +1492,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Detach all glyphs from cursors and place them back in lines.
|
||||
#[profile(Debug)]
|
||||
pub fn detach_glyphs_from_cursors(&self) {
|
||||
let selection_map = self.selection_map.borrow();
|
||||
for (&line, cursor_map) in &selection_map.location_map {
|
||||
@ -1754,6 +1761,7 @@ impl TextModel {
|
||||
}
|
||||
|
||||
/// Position all lines in the provided line range. The range has to be sorted.
|
||||
#[profile(Debug)]
|
||||
fn position_sorted_line_ranges(
|
||||
&self,
|
||||
sorted_line_ranges: impl Iterator<Item = RangeInclusive<ViewLine>>,
|
||||
|
@ -386,6 +386,7 @@ impl Family for NonVariableFamily {
|
||||
|
||||
impl Family for VariableFamily {
|
||||
type Variations = VariationAxes;
|
||||
#[profile(Debug)]
|
||||
fn update_msdfgen_variations(&self, variations: &Self::Variations) {
|
||||
if let Some(face) = self.face.borrow().as_ref() {
|
||||
if self.last_axes.borrow().as_ref() != Some(variations) {
|
||||
|
@ -569,6 +569,7 @@ impl System {
|
||||
|
||||
/// Create new glyph. In the returned glyph the further parameters (position,size,character)
|
||||
/// may be set.
|
||||
#[profile(Debug)]
|
||||
pub fn new_glyph(&self) -> Glyph {
|
||||
let frp = Frp::new();
|
||||
#[allow(clippy::clone_on_copy)]
|
||||
|
@ -75,6 +75,7 @@ impl GlyphRenderInfo {
|
||||
|
||||
/// Load new [`GlyphRenderInfo`] from msdf_sys font handle. This also extends the atlas with
|
||||
/// MSDF generated for this character.
|
||||
#[profile(Debug)]
|
||||
pub fn load(handle: &msdf_sys::OwnedFace, glyph_id: GlyphId, atlas: &msdf::Texture) -> Self {
|
||||
let params = Self::MSDF_PARAMS;
|
||||
let msdf = Msdf::generate_by_index(handle, glyph_id.0 as usize, ¶ms);
|
||||
|
@ -57,6 +57,7 @@ impl<T: mix::Mixable + frp::Data> Animation<T>
|
||||
where mix::Repr<T>: inertia::Value
|
||||
{
|
||||
/// Constructor. The initial value of the animation is set to `default`.
|
||||
#[profile(Debug)]
|
||||
pub fn new(network: &frp::Network) -> Self {
|
||||
frp::extend! { network
|
||||
value_src <- any_mut::<T>();
|
||||
|
@ -75,6 +75,10 @@ macro_rules! define_bindings {
|
||||
let shape = dom.shape.clone_ref();
|
||||
let dispatcher = dispatchers.$name.clone_ref();
|
||||
let closure : MouseEventJsClosure = Closure::new(move |event:JsValue| {
|
||||
let _profiler = profiler::start_task!(
|
||||
profiler::APP_LIFETIME,
|
||||
concat!("mouse_", stringify!($name))
|
||||
);
|
||||
let shape = shape.value();
|
||||
let event = event.unchecked_into::<web::$js_event>();
|
||||
dispatcher.run_all(&event::$target::new(event,shape))
|
||||
|
@ -1707,6 +1707,7 @@ impl Model {
|
||||
|
||||
/// Recompute the transformation matrix of the display object tree starting with this object and
|
||||
/// traversing all of its dirty children.
|
||||
#[profile(Detail)]
|
||||
pub fn update(&self, scene: &Scene) {
|
||||
self.refresh_layout();
|
||||
let origin0 = Matrix4::identity();
|
||||
|
@ -8,6 +8,7 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
enso-debug-api = { path = "../../../debug-api" }
|
||||
enso-frp = { path = "../../../frp" }
|
||||
enso-profiler-data = { path = "../../../profiler/data" }
|
||||
enso-profiler-demo-data = { path = "../../../profiler/demo-data" }
|
||||
|
@ -39,7 +39,7 @@ use ensogl_flame_graph as flame_graph;
|
||||
#[wasm_bindgen]
|
||||
#[allow(dead_code)]
|
||||
pub async fn entry_point_render_profile_flamegraph() {
|
||||
let data = get_data().await;
|
||||
let data = get_data().await.unwrap();
|
||||
let profile: profiler_data::Profile<profiler_data::OpaqueMetadata> = data.parse().unwrap();
|
||||
ensogl_text_msdf::initialized().await;
|
||||
use ensogl_core::display::object::ObjectOps;
|
||||
@ -76,32 +76,13 @@ pub async fn entry_point_render_profile_flamegraph() {
|
||||
// implement some way of invoking this scene with paths to multiple profile files, and then
|
||||
// we'd replace this. For now, this is a copy of the file-loading code from the `render-profile`
|
||||
// scene.
|
||||
/// Read profile data from a file. The file must be located at `/profile.json` in the root of the
|
||||
/// directory that will be made available by the webserver, i.e. `enso/dist/content`.
|
||||
async fn get_data() -> String {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
let url = "assets/profile.json";
|
||||
let mut opts = web_sys::RequestInit::new();
|
||||
opts.method("GET");
|
||||
opts.mode(web_sys::RequestMode::Cors);
|
||||
let request = web_sys::Request::new_with_str_and_init(url, &opts).unwrap();
|
||||
request.headers().set("Accept", "application/json").unwrap();
|
||||
let window = web_sys::window().unwrap();
|
||||
let response = window.fetch_with_request(&request);
|
||||
let response = wasm_bindgen_futures::JsFuture::from(response).await.unwrap();
|
||||
assert!(response.is_instance_of::<web_sys::Response>());
|
||||
let response: web_sys::Response = response.dyn_into().unwrap();
|
||||
if !response.ok() {
|
||||
error!(
|
||||
"Error retrieving profile file from {url}: {}. Falling back to demo data.",
|
||||
response.status_text()
|
||||
);
|
||||
return enso_profiler_demo_data::create_data().await;
|
||||
/// Read profile data from a file specified on the command line.
|
||||
async fn get_data() -> Option<String> {
|
||||
let files = enso_debug_api::load_profiles()?.await;
|
||||
if files.len() > 1 {
|
||||
error!("Entry point profiling-run-graph doesn't support multiple profile file arguments.");
|
||||
}
|
||||
let data = response.text().unwrap();
|
||||
let data = wasm_bindgen_futures::JsFuture::from(data).await.unwrap();
|
||||
data.as_string().unwrap()
|
||||
files.into_iter().next()
|
||||
}
|
||||
|
||||
fn init_theme(scene: &display::Scene) {
|
||||
|
@ -80,6 +80,7 @@ pub fn set_spawner(spawner_to_set: impl LocalSpawn + 'static) {
|
||||
pub fn spawn(f: impl Future<Output = ()> + 'static) {
|
||||
SPAWNER.with(|s| s.spawn(f));
|
||||
}
|
||||
|
||||
/// Process stream elements while object under `weak` handle exists.
|
||||
///
|
||||
/// Like [`utils::channel::process_stream_with_handle`] but automatically spawns the processor.
|
||||
|
@ -112,10 +112,10 @@ macro_rules! _new_dynamic_network {
|
||||
#[macro_export]
|
||||
macro_rules! new_bridge_network {
|
||||
([$($($path:ident).*),*] $label:ident $($ts:tt)*) => {
|
||||
let _birdge_network_ = $crate::Network::new(stringify!($label));
|
||||
$crate::extend! { _birdge_network_ $($ts)* }
|
||||
let _birdge_network_ = $crate::BridgeNetwork::from(_birdge_network_);
|
||||
$($($path).*.register_bridge_network(&_birdge_network_);)*
|
||||
let _bridge_network_ = $crate::Network::new(stringify!($label));
|
||||
$crate::extend! { _bridge_network_ $($ts)* }
|
||||
let _bridge_network_ = $crate::BridgeNetwork::from(_bridge_network_);
|
||||
$($($path).*.register_bridge_network(&_bridge_network_);)*
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user