Skip to content

Commit b0a16e0

Browse files
committed
Merge remote-tracking branch 'upstream/master' into dom-bundle
2 parents 9ee4561 + c7599c5 commit b0a16e0

22 files changed

Lines changed: 155 additions & 132 deletions

File tree

packages/yew/src/dom_bundle/blist.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -304,22 +304,20 @@ impl BList {
304304
// hot path
305305
// We know that idx >= run.end_idx, so this node doesn't need to shift
306306
Some(run) => run.end_idx = idx,
307-
None => {
308-
match idx.cmp(&barrier_idx) {
309-
// peep hole optimization, don't start a run as the element is already where it should be
310-
Ordering::Equal => barrier_idx += 1,
311-
// shift the node unconditionally, don't start a run
312-
Ordering::Less => writer.shift(&mut r_bundle),
313-
// start a run
314-
Ordering::Greater => {
315-
current_run = Some(RunInformation {
316-
start_writer: writer.clone(),
317-
start_idx: replacements.len(),
318-
end_idx: idx,
319-
})
320-
}
307+
None => match idx.cmp(&barrier_idx) {
308+
// peep hole optimization, don't start a run as the element is already where it should be
309+
Ordering::Equal => barrier_idx += 1,
310+
// shift the node unconditionally, don't start a run
311+
Ordering::Less => writer.shift(&mut r_bundle),
312+
// start a run
313+
Ordering::Greater => {
314+
current_run = Some(RunInformation {
315+
start_writer: writer.clone(),
316+
start_idx: replacements.len(),
317+
end_idx: idx,
318+
})
321319
}
322-
}
320+
},
323321
}
324322
writer = writer.patch(l, &mut r_bundle);
325323
r_bundle

packages/yew/src/html/component/lifecycle.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@ impl<COMP: BaseComponent> Runnable for UpdateRunner<COMP> {
125125
RenderRunner {
126126
state: self.state.clone(),
127127
},
128-
RenderedRunner {
129-
state: self.state.clone(),
130-
},
131128
);
132129
// Only run from the scheduler, so no need to call `scheduler::start()`
133130
}
@@ -174,9 +171,24 @@ impl<COMP: BaseComponent> Runnable for RenderRunner<COMP> {
174171

175172
suspense.resume(m);
176173
}
174+
177175
let scope = state.context.scope.clone().into();
178176
let node = state.render_state.reconcile(root, &scope);
179177
state.node_ref.link(node);
178+
179+
if state.render_state.should_trigger_rendered() {
180+
let first_render = !state.has_rendered;
181+
state.has_rendered = true;
182+
183+
scheduler::push_component_rendered(
184+
self.state.as_ptr() as usize,
185+
RenderedRunner {
186+
state: self.state.clone(),
187+
first_render,
188+
},
189+
first_render,
190+
);
191+
}
180192
}
181193

182194
Err(RenderError::Suspended(m)) => {
@@ -192,9 +204,6 @@ impl<COMP: BaseComponent> Runnable for RenderRunner<COMP> {
192204
RenderRunner {
193205
state: shared_state.clone(),
194206
},
195-
RenderedRunner {
196-
state: shared_state,
197-
},
198207
);
199208
} else {
200209
// We schedule a render after current suspension is resumed.
@@ -212,9 +221,6 @@ impl<COMP: BaseComponent> Runnable for RenderRunner<COMP> {
212221
RenderRunner {
213222
state: shared_state.clone(),
214223
},
215-
RenderedRunner {
216-
state: shared_state.clone(),
217-
},
218224
);
219225
}));
220226

@@ -234,8 +240,9 @@ impl<COMP: BaseComponent> Runnable for RenderRunner<COMP> {
234240
}
235241
}
236242

237-
pub struct RenderedRunner<COMP: BaseComponent> {
238-
pub state: Shared<Option<ComponentState<COMP>>>,
243+
struct RenderedRunner<COMP: BaseComponent> {
244+
state: Shared<Option<ComponentState<COMP>>>,
245+
first_render: bool,
239246
}
240247

241248
impl<COMP: BaseComponent> Runnable for RenderedRunner<COMP> {
@@ -244,10 +251,8 @@ impl<COMP: BaseComponent> Runnable for RenderedRunner<COMP> {
244251
#[cfg(debug_assertions)]
245252
super::log_event(state.vcomp_id, "rendered");
246253

247-
if state.suspension.is_none() && state.render_state.should_trigger_rendered() {
248-
let first_render = !state.has_rendered;
249-
state.component.rendered(&state.context, first_render);
250-
state.has_rendered = true;
254+
if state.suspension.is_none() {
255+
state.component.rendered(&state.context, self.first_render);
251256
}
252257
}
253258
}

packages/yew/src/html/component/scope.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! Component scope module
22
33
use super::lifecycle::{
4-
ComponentState, CreateRunner, DestroyRunner, RenderRunner, RenderedRunner, UpdateEvent,
5-
UpdateRunner,
4+
ComponentState, CreateRunner, DestroyRunner, RenderRunner, UpdateEvent, UpdateRunner,
65
};
76
use crate::callback::Callback;
87
use crate::context::{ContextHandle, ContextProvider};
@@ -222,9 +221,6 @@ impl<COMP: BaseComponent> Scope<COMP> {
222221
RenderRunner {
223222
state: self.state.clone(),
224223
},
225-
RenderedRunner {
226-
state: self.state.clone(),
227-
},
228224
);
229225
// Not guaranteed to already have the scheduler started
230226
scheduler::start();

packages/yew/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ where
327327
COMP: BaseComponent,
328328
COMP::Properties: Default,
329329
{
330-
start_app_with_props_in_element(element, COMP::Properties::default())
330+
start_app_with_props_in_element::<COMP>(element, COMP::Properties::default())
331331
}
332332

333333
/// Starts an yew app mounted to the body of the document.
@@ -337,7 +337,7 @@ where
337337
COMP: BaseComponent,
338338
COMP::Properties: Default,
339339
{
340-
start_app_with_props(COMP::Properties::default())
340+
start_app_with_props::<COMP>(COMP::Properties::default())
341341
}
342342

343343
/// The main entry point of a Yew application. This function does the
@@ -359,7 +359,7 @@ pub fn start_app_with_props<COMP>(props: COMP::Properties) -> AppHandle<COMP>
359359
where
360360
COMP: BaseComponent,
361361
{
362-
start_app_with_props_in_element(
362+
start_app_with_props_in_element::<COMP>(
363363
gloo_utils::document()
364364
.body()
365365
.expect("no body node found")
@@ -378,7 +378,7 @@ where
378378
/// ```
379379
pub mod prelude {
380380
pub use crate::callback::Callback;
381-
pub use crate::context::ContextProvider;
381+
pub use crate::context::{ContextHandle, ContextProvider};
382382
pub use crate::dom_bundle::AppHandle;
383383
pub use crate::events::*;
384384
pub use crate::html::{

packages/yew/src/scheduler.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,10 @@ pub fn push(runnable: Box<dyn Runnable>) {
5858
pub(crate) fn push_component_create(
5959
create: impl Runnable + 'static,
6060
first_render: impl Runnable + 'static,
61-
first_rendered: impl Runnable + 'static,
6261
) {
6362
with(|s| {
6463
s.create.push(Box::new(create));
6564
s.render_first.push_back(Box::new(first_render));
66-
s.rendered_first.push(Box::new(first_rendered));
6765
});
6866
}
6967

@@ -73,14 +71,25 @@ pub(crate) fn push_component_destroy(runnable: impl Runnable + 'static) {
7371
}
7472

7573
/// Push a component render and rendered [Runnable]s to be executed
76-
pub(crate) fn push_component_render(
74+
pub(crate) fn push_component_render(component_id: usize, render: impl Runnable + 'static) {
75+
with(|s| {
76+
s.render.schedule(component_id, Box::new(render));
77+
});
78+
}
79+
80+
pub(crate) fn push_component_rendered(
7781
component_id: usize,
78-
render: impl Runnable + 'static,
7982
rendered: impl Runnable + 'static,
83+
first_render: bool,
8084
) {
8185
with(|s| {
82-
s.render.schedule(component_id, Box::new(render));
83-
s.rendered.schedule(component_id, Box::new(rendered));
86+
let rendered = Box::new(rendered);
87+
88+
if first_render {
89+
s.rendered_first.push(rendered);
90+
} else {
91+
s.rendered.schedule(component_id, rendered);
92+
}
8493
});
8594
}
8695

tools/benchmark-hooks/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ crate-type = ["cdylib"]
1010
[dependencies]
1111
rand = { version = "0.8.4", features = ["small_rng"] }
1212
getrandom = { version = "0.2.1", features = ["js"] }
13-
wasm-bindgen = "0.2.78"
13+
wasm-bindgen = "=0.2.78"
1414
web-sys = { version = "0.3.55", features = ["Window"]}
1515
yew = "0.19.3"
1616

tools/benchmark-struct/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ crate-type = ["cdylib"]
1010
[dependencies]
1111
rand = { version = "0.8.4", features = ["small_rng"] }
1212
getrandom = { version = "0.2.1", features = ["js"] }
13-
wasm-bindgen = "0.2.78"
13+
wasm-bindgen = "=0.2.78"
1414
web-sys = { version = "0.3.55", features = ["Window"]}
1515
yew = "0.19.3"
1616

website/docs/advanced-topics/how-it-works.mdx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@ Using the `html!` macro can feel pretty magic, but it has nothing to hide. If yo
2323
how it works, try expanding the `html!` macro calls in your program. There's a useful command called
2424
`cargo expand` which allows you to see the expansion of Rust macros. `cargo expand` isn't shipped with
2525
`cargo` by default so you'll need to install it with `cargo install cargo-expand` if you haven't
26-
already.
26+
already. [Rust-Analyzer](https://rust-analyzer.github.io/) also provides a mechanism for
27+
[obtaining macro output from within an IDE](https://rust-analyzer.github.io/manual.html#expand-macro-recursively).
2728

28-
Note that when viewing expanded macro code, you're likely to encounter unusually verbose code. The
29-
reason is because generated code can sometimes clash with other code in an application. In order
30-
to prevent issues, `proc_macro` "hygiene" is adhered to. Some examples include:
29+
Output from the `html!` macro is often pretty terse! This is a feature: machine-generated code can
30+
sometimes clash with other code in an application. In order to prevent issues, `proc_macro`
31+
"hygiene" is adhered to. Some examples include:
3132

3233
1. Instead of using `yew::<module>` the macro generates `::yew::<module>` to make sure that the
3334
Yew package is referenced correctly. This is also why `::alloc::vec::Vec::new()` is called instead
3435
of just `Vec::new()`.
35-
2. Due to potential trait method name collisions, `<Type as Trait>` is used to make sure that we're using items from the right trait.
36+
2. Due to potential trait method name collisions, `<Type as Trait>` is used to make sure that we're
37+
using members from the correct trait.
3638

3739
## What is a virtual DOM?
3840

website/docs/advanced-topics/portals.mdx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@ title: "Portals"
33
description: "Rendering into out-of-tree DOM nodes"
44
---
55

6-
## How to think about portals?
6+
## What is a portal?
77

88
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
99
`yew::create_portal(child, host)` returns a `Html` value that renders `child` not hierarchically under its parent component,
1010
but as a child of the `host` element.
1111

1212
## Usage
1313

14-
Typical uses of portals can include modal dialogs and hovercards, as well as more technical applications such as controlling the contents of an element's [`shadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/Element/shadowRoot), appending stylesheets to the surrounding document's `<head>` and collecting referenced elements inside a central `<defs>` element of an `<svg>`.
14+
Typical uses of portals can include modal dialogs and hovercards, as well as more technical applications
15+
such as controlling the contents of an element's
16+
[`shadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/Element/shadowRoot), appending
17+
stylesheets to the surrounding document's `<head>` and collecting referenced elements inside a
18+
central `<defs>` element of an `<svg>`.
1519

16-
Note that `yew::create_portal` is a rather low-level building block, on which other components should be built that provide the interface for your specific use case. As an example, here is a simple modal dialogue that renders its `children` into an element outside `yew`'s control, identified by the `id="modal_host"`.
20+
Note that `yew::create_portal` is a low-level building block. Libraries should use it to implement
21+
higher-level APIs which can then be consumed by applications. For example, here is a
22+
simple modal dialogue that renders its `children` into an element outside `yew`'s control,
23+
identified by the `id="modal_host"`.
1724

1825
```rust
1926
use yew::{html, create_portal, function_component, Children, Properties, Html};

website/docs/concepts/html/events.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ for the behaviour of `JsCast` but with the smaller scope of events and their tar
289289
similar to what you would using `JsCast`.
290290
:::
291291

292-
The `TargetCast` trait builds off of `JsCast` and is specialized towards getting typed event targets
293-
from events.
292+
The `TargetCast` trait is built on top of `JsCast` and is specialized towards getting typed event
293+
targets from events.
294294

295295
`TargetCast` comes with Yew so no need to add a dependency in order to use the trait methods on events
296296
but it works in a very similar way to `JsCast`.

0 commit comments

Comments
 (0)