Clean up comments, generics names, and variable names (#752)

This commit is contained in:
Justin Starry 2019-11-23 16:50:20 -05:00 committed by GitHub
parent b4c141560a
commit c439a3d477
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 113 additions and 106 deletions

View File

@ -157,7 +157,7 @@ impl Agent for Worker {
type Input = Request;
type Output = Response;
// Create an instance with a link to agent's environment.
// Create an instance with a link to the agent.
fn create(link: AgentLink<Self>) -> Self {
Worker { link }
}
@ -271,12 +271,9 @@ html! {
}
```
### Virtual DOM, independent loops, fine updates
### Virtual DOM
Yew uses its own **virtual-dom** implementation. It updates the browser's DOM
with tiny patches when properties of elements have changed. Every component lives
in its own independent loop interacting with the environment (`Scope`) through message passing
and supports a fine control of rendering.
Yew uses its own **virtual-dom** implementation. It updates the browser's DOM with tiny patches when properties of elements have changed. Every component can be interacted with using its (`Scope`) to pass messages and trigger updates.
The `ShouldRender` returns the value which informs the loop when the component should be re-rendered:

View File

@ -859,8 +859,8 @@ where
return;
}
match self.update {
AgentUpdate::Create(env) => {
this.agent = Some(AGN::create(env));
AgentUpdate::Create(link) => {
this.agent = Some(AGN::create(link));
}
AgentUpdate::Message(msg) => {
this.agent

View File

@ -330,7 +330,7 @@ impl NodeRef {
}
}
/// Should be rendered relative to context and component environment.
/// Trait for rendering virtual DOM elements
pub trait Renderable<COMP: Component> {
/// Called by rendering loop.
fn render(&self) -> Html<COMP>;

View File

@ -6,7 +6,7 @@ use std::fmt;
use std::rc::Rc;
use stdweb::web::Element;
/// Updates for a `Components` instance. Used by scope sender.
/// Updates for a `Component` instance. Used by scope sender.
pub(crate) enum ComponentUpdate<COMP: Component> {
/// Wraps messages for a component.
Message(COMP::Message),
@ -16,8 +16,7 @@ pub(crate) enum ComponentUpdate<COMP: Component> {
Properties(COMP::Properties),
}
/// A context which contains a bridge to send a messages to a loop.
/// Mostly services uses it.
/// A context which allows sending messages to a component.
pub struct Scope<COMP: Component> {
shared_state: Shared<ComponentState<COMP>>,
}
@ -60,7 +59,7 @@ impl<COMP: Component> Scope<COMP> {
let mut scope = self.clone();
let link = ComponentLink::connect(&scope);
let ready_state = ReadyState {
env: self.clone(),
scope: self.clone(),
element,
node_ref,
link,
@ -136,7 +135,7 @@ impl<COMP: Component> fmt::Display for ComponentState<COMP> {
}
struct ReadyState<COMP: Component> {
env: Scope<COMP>,
scope: Scope<COMP>,
element: Element,
node_ref: NodeRef,
props: COMP::Properties,
@ -148,7 +147,7 @@ impl<COMP: Component> ReadyState<COMP> {
fn create(self) -> CreatedState<COMP> {
CreatedState {
component: COMP::create(self.props, self.link),
env: self.env,
scope: self.scope,
element: self.element,
last_frame: self.ancestor,
node_ref: self.node_ref,
@ -157,7 +156,7 @@ impl<COMP: Component> ReadyState<COMP> {
}
struct CreatedState<COMP: Component> {
env: Scope<COMP>,
scope: Scope<COMP>,
element: Element,
component: COMP,
last_frame: Option<VNode<COMP>>,
@ -176,7 +175,7 @@ impl<COMP: Component> CreatedState<COMP> {
fn update(mut self) -> Self {
let mut next_frame = self.component.render();
let node = next_frame.apply(&self.element, None, self.last_frame, &self.env);
let node = next_frame.apply(&self.element, None, self.last_frame, &self.scope);
self.node_ref.set(node);
self.last_frame = Some(next_frame);
self

View File

@ -162,7 +162,7 @@ pub trait VDiff {
/// find where to put the node.
/// - `ancestor`: the node that this node will be replacing in the DOM.
/// This method will _always_ remove the `ancestor` from the `parent`.
/// - `env`: the `Env`.
/// - `parent_scope`: the parent `Scope` used for passing messages to the parent `Component`.
///
/// ### Internal Behavior Notice:
///
@ -177,6 +177,6 @@ pub trait VDiff {
parent: &Element,
previous_sibling: Option<&Node>,
ancestor: Option<VNode<Self::Component>>,
scope: &Scope<Self::Component>,
parent_scope: &Scope<Self::Component>,
) -> Option<Node>;
}

View File

@ -14,8 +14,8 @@ struct Hidden;
type HiddenScope = *mut Hidden;
/// The method generates an instance of a (child) component.
type Generator<COMP> = dyn FnOnce(GeneratorType, Scope<COMP>) -> Mounted;
/// The method generates an instance of a component.
type Generator<PARENT> = dyn FnOnce(GeneratorType, Scope<PARENT>) -> Mounted;
/// Components can be generated by mounting or by overwriting an old component.
enum GeneratorType {
@ -23,19 +23,13 @@ enum GeneratorType {
Overwrite(TypeId, HiddenScope),
}
/// A reference to unknown scope which will be attached later with a generator function.
pub type ScopeHolder<COMP> = Rc<RefCell<Option<Scope<COMP>>>>;
/// A reference to the parent's scope which will be used later to send messages.
pub type ScopeHolder<PARENT> = Rc<RefCell<Option<Scope<PARENT>>>>;
/// A virtual component.
pub struct VComp<COMP: Component> {
pub struct VComp<PARENT: Component> {
type_id: TypeId,
state: Rc<RefCell<MountState<COMP>>>,
}
impl<COMP: Component> fmt::Debug for VComp<COMP> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("VComp<_>")
}
state: Rc<RefCell<MountState<PARENT>>>,
}
/// A virtual child component.
@ -48,12 +42,6 @@ pub struct VChild<SELF: Component, PARENT: Component> {
node_ref: NodeRef,
}
impl<SELF: Component, PARENT: Component> fmt::Debug for VChild<SELF, PARENT> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("VChild<_,_>")
}
}
impl<SELF, PARENT> VChild<SELF, PARENT>
where
SELF: Component,
@ -69,26 +57,26 @@ where
}
}
impl<COMP, CHILD> From<VChild<CHILD, COMP>> for VComp<COMP>
impl<SELF, PARENT> From<VChild<SELF, PARENT>> for VComp<PARENT>
where
COMP: Component,
CHILD: Component,
SELF: Component,
PARENT: Component,
{
fn from(vchild: VChild<CHILD, COMP>) -> Self {
VComp::new::<CHILD>(vchild.props, vchild.scope, vchild.node_ref)
fn from(vchild: VChild<SELF, PARENT>) -> Self {
VComp::new::<SELF>(vchild.props, vchild.scope, vchild.node_ref)
}
}
enum MountState<COMP: Component> {
Unmounted(Unmounted<COMP>),
enum MountState<PARENT: Component> {
Unmounted(Unmounted<PARENT>),
Mounted(Mounted),
Mounting,
Detached,
Overwritten,
}
struct Unmounted<COMP: Component> {
generator: Box<Generator<COMP>>,
struct Unmounted<PARENT: Component> {
generator: Box<Generator<PARENT>>,
}
struct Mounted {
@ -97,21 +85,21 @@ struct Mounted {
destroyer: Box<dyn FnOnce()>,
}
impl<COMP: Component> VComp<COMP> {
impl<PARENT: Component> VComp<PARENT> {
/// This method prepares a generator to make a new instance of the `Component`.
pub fn new<CHILD>(
props: CHILD::Properties,
scope_holder: ScopeHolder<COMP>,
pub fn new<SELF>(
props: SELF::Properties,
scope_holder: ScopeHolder<PARENT>,
node_ref: NodeRef,
) -> Self
where
CHILD: Component,
SELF: Component,
{
let generator = move |generator_type: GeneratorType, parent: Scope<COMP>| -> Mounted {
let generator = move |generator_type: GeneratorType, parent: Scope<PARENT>| -> Mounted {
*scope_holder.borrow_mut() = Some(parent);
match generator_type {
GeneratorType::Mount(element, ancestor) => {
let scope: Scope<CHILD> = Scope::new();
let scope: Scope<SELF> = Scope::new();
// TODO Consider to send ComponentUpdate::Create after `mount_in_place` call
let mut scope = scope.mount_in_place(
@ -128,12 +116,12 @@ impl<COMP: Component> VComp<COMP> {
}
}
GeneratorType::Overwrite(type_id, scope) => {
if type_id != TypeId::of::<CHILD>() {
if type_id != TypeId::of::<SELF>() {
panic!("tried to overwrite a different type of component");
}
let mut scope = unsafe {
let raw: *mut Scope<CHILD> = scope as *mut Scope<CHILD>;
let raw: *mut Scope<SELF> = scope as *mut Scope<SELF>;
*Box::from_raw(raw)
};
@ -149,7 +137,7 @@ impl<COMP: Component> VComp<COMP> {
};
VComp {
type_id: TypeId::of::<CHILD>(),
type_id: TypeId::of::<SELF>(),
state: Rc::new(RefCell::new(MountState::Unmounted(Unmounted {
generator: Box::new(generator),
}))),
@ -157,83 +145,83 @@ impl<COMP: Component> VComp<COMP> {
}
}
/// Converts property and attach empty scope holder which will be activated later.
pub trait Transformer<COMP: Component, FROM, TO> {
/// Transforms properties and attaches a parent scope holder to callbacks for sending messages.
pub trait Transformer<PARENT: Component, FROM, TO> {
/// Transforms one type to another.
fn transform(scope_holder: ScopeHolder<COMP>, from: FROM) -> TO;
fn transform(scope_holder: ScopeHolder<PARENT>, from: FROM) -> TO;
}
impl<COMP, T> Transformer<COMP, T, T> for VComp<COMP>
impl<PARENT, T> Transformer<PARENT, T, T> for VComp<PARENT>
where
COMP: Component,
PARENT: Component,
{
fn transform(_: ScopeHolder<COMP>, from: T) -> T {
fn transform(_: ScopeHolder<PARENT>, from: T) -> T {
from
}
}
impl<'a, COMP, T> Transformer<COMP, &'a T, T> for VComp<COMP>
impl<'a, PARENT, T> Transformer<PARENT, &'a T, T> for VComp<PARENT>
where
COMP: Component,
PARENT: Component,
T: Clone,
{
fn transform(_: ScopeHolder<COMP>, from: &'a T) -> T {
fn transform(_: ScopeHolder<PARENT>, from: &'a T) -> T {
from.clone()
}
}
impl<'a, COMP> Transformer<COMP, &'a str, String> for VComp<COMP>
impl<'a, PARENT> Transformer<PARENT, &'a str, String> for VComp<PARENT>
where
COMP: Component,
PARENT: Component,
{
fn transform(_: ScopeHolder<COMP>, from: &'a str) -> String {
fn transform(_: ScopeHolder<PARENT>, from: &'a str) -> String {
from.to_owned()
}
}
impl<'a, COMP, F, IN> Transformer<COMP, F, Callback<IN>> for VComp<COMP>
impl<'a, PARENT, F, IN> Transformer<PARENT, F, Callback<IN>> for VComp<PARENT>
where
COMP: Component,
F: Fn(IN) -> COMP::Message + 'static,
PARENT: Component,
F: Fn(IN) -> PARENT::Message + 'static,
{
fn transform(scope: ScopeHolder<COMP>, from: F) -> Callback<IN> {
fn transform(scope: ScopeHolder<PARENT>, from: F) -> Callback<IN> {
let callback = move |arg| {
let msg = from(arg);
if let Some(ref mut sender) = *scope.borrow_mut() {
sender.send_message(msg);
} else {
panic!("unactivated callback, parent component have to activate it");
panic!("Parent component hasn't activated this callback yet");
}
};
callback.into()
}
}
impl<'a, COMP, F, IN> Transformer<COMP, F, Option<Callback<IN>>> for VComp<COMP>
impl<'a, PARENT, F, IN> Transformer<PARENT, F, Option<Callback<IN>>> for VComp<PARENT>
where
COMP: Component,
F: Fn(IN) -> COMP::Message + 'static,
PARENT: Component,
F: Fn(IN) -> PARENT::Message + 'static,
{
fn transform(scope: ScopeHolder<COMP>, from: F) -> Option<Callback<IN>> {
fn transform(scope: ScopeHolder<PARENT>, from: F) -> Option<Callback<IN>> {
let callback = move |arg| {
let msg = from(arg);
if let Some(ref mut sender) = *scope.borrow_mut() {
sender.send_message(msg);
} else {
panic!("unactivated callback, parent component have to activate it");
panic!("Parent component hasn't activated this callback yet");
}
};
Some(callback.into())
}
}
impl<COMP: Component> Unmounted<COMP> {
/// mount a virtual component with a generator.
impl<PARENT: Component> Unmounted<PARENT> {
/// Mount a virtual component using a generator.
fn mount<T: INode>(
self,
parent: &T,
ancestor: Node, // Any dummy expected
env: Scope<COMP>,
parent_scope: Scope<PARENT>,
) -> Mounted {
let element: Element = parent
.as_node()
@ -241,12 +229,12 @@ impl<COMP: Component> Unmounted<COMP> {
.to_owned()
.try_into()
.expect("element expected to mount VComp");
(self.generator)(GeneratorType::Mount(element, ancestor), env)
(self.generator)(GeneratorType::Mount(element, ancestor), parent_scope)
}
/// Overwrite an existing virtual component with a generator.
fn replace(self, type_id: TypeId, old: Mounted, env: Scope<COMP>) -> Mounted {
(self.generator)(GeneratorType::Overwrite(type_id, old.scope), env)
/// Overwrite an existing virtual component using a generator.
fn replace(self, type_id: TypeId, old: Mounted, parent_scope: Scope<PARENT>) -> Mounted {
(self.generator)(GeneratorType::Overwrite(type_id, old.scope), parent_scope)
}
}
@ -285,7 +273,7 @@ where
parent: &Element,
previous_sibling: Option<&Node>,
ancestor: Option<VNode<Self::Component>>,
env: &Scope<Self::Component>,
parent_scope: &Scope<Self::Component>,
) -> Option<Node> {
match self.state.replace(MountState::Mounting) {
MountState::Unmounted(this) => {
@ -312,10 +300,8 @@ where
let mounted = match reform {
Reform::Keep(type_id, mounted) => {
// Send properties update when component still be rendered.
// But for the first initialization mount gets initial
// properties directly without this channel.
this.replace(type_id, mounted, env.clone())
// Send properties update when the component is already rendered.
this.replace(type_id, mounted, parent_scope.clone())
}
Reform::Before(before) => {
// This is a workaround, because component should be mounted
@ -338,7 +324,7 @@ where
}
}
let node = element.as_node().to_owned();
this.mount(parent, node, env.clone())
this.mount(parent, node, parent_scope.clone())
}
};
@ -354,8 +340,20 @@ where
}
}
impl<COMP: Component> PartialEq for VComp<COMP> {
fn eq(&self, other: &VComp<COMP>) -> bool {
impl<C: Component> PartialEq for VComp<C> {
fn eq(&self, other: &VComp<C>) -> bool {
self.type_id == other.type_id
}
}
impl<C: Component> fmt::Debug for VComp<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("VComp<_>")
}
}
impl<SELF: Component, PARENT: Component> fmt::Debug for VChild<SELF, PARENT> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("VChild<_,_>")
}
}

View File

@ -4,7 +4,7 @@ use crate::html::{Component, Scope};
use stdweb::web::{Element, Node};
/// This struct represents a fragment of the Virtual DOM tree.
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct VList<COMP: Component> {
/// The list of children nodes. Which also could have their own children.
pub children: Vec<VNode<COMP>>,
@ -46,7 +46,7 @@ impl<COMP: Component> VDiff for VList<COMP> {
parent: &Element,
previous_sibling: Option<&Node>,
ancestor: Option<VNode<Self::Component>>,
env: &Scope<Self::Component>,
parent_scope: &Scope<Self::Component>,
) -> Option<Node> {
// Reuse previous_sibling, because fragment reuse parent
let mut previous_sibling = previous_sibling.cloned();
@ -81,11 +81,16 @@ impl<COMP: Component> VDiff for VList<COMP> {
loop {
match (lefts.next(), rights.next()) {
(Some(left), Some(right)) => {
previous_sibling =
left.apply(parent, previous_sibling.as_ref(), Some(right), &env);
previous_sibling = left.apply(
parent,
previous_sibling.as_ref(),
Some(right),
&parent_scope,
);
}
(Some(left), None) => {
previous_sibling = left.apply(parent, previous_sibling.as_ref(), None, &env);
previous_sibling =
left.apply(parent, previous_sibling.as_ref(), None, &parent_scope);
}
(None, Some(ref mut right)) => {
right.detach(parent);

View File

@ -46,13 +46,21 @@ impl<COMP: Component> VDiff for VNode<COMP> {
parent: &Element,
previous_sibling: Option<&Node>,
ancestor: Option<VNode<Self::Component>>,
env: &Scope<Self::Component>,
parent_scope: &Scope<Self::Component>,
) -> Option<Node> {
match *self {
VNode::VTag(ref mut vtag) => vtag.apply(parent, previous_sibling, ancestor, env),
VNode::VText(ref mut vtext) => vtext.apply(parent, previous_sibling, ancestor, env),
VNode::VComp(ref mut vcomp) => vcomp.apply(parent, previous_sibling, ancestor, env),
VNode::VList(ref mut vlist) => vlist.apply(parent, previous_sibling, ancestor, env),
VNode::VTag(ref mut vtag) => {
vtag.apply(parent, previous_sibling, ancestor, parent_scope)
}
VNode::VText(ref mut vtext) => {
vtext.apply(parent, previous_sibling, ancestor, parent_scope)
}
VNode::VComp(ref mut vcomp) => {
vcomp.apply(parent, previous_sibling, ancestor, parent_scope)
}
VNode::VList(ref mut vlist) => {
vlist.apply(parent, previous_sibling, ancestor, parent_scope)
}
VNode::VRef(ref mut node) => {
let sibling = match ancestor {
Some(mut n) => n.detach(parent),

View File

@ -373,7 +373,7 @@ impl<COMP: Component> VDiff for VTag<COMP> {
parent: &Element,
previous_sibling: Option<&Node>,
ancestor: Option<VNode<Self::Component>>,
env: &Scope<Self::Component>,
parent_scope: &Scope<Self::Component>,
) -> Option<Node> {
assert!(
self.reference.is_none(),
@ -456,7 +456,7 @@ impl<COMP: Component> VDiff for VTag<COMP> {
}
for mut listener in self.listeners.drain(..) {
let handle = listener.attach(&element, env.clone());
let handle = listener.attach(&element, parent_scope.clone());
self.captured.push(handle);
}
@ -469,7 +469,7 @@ impl<COMP: Component> VDiff for VTag<COMP> {
match (self_children.next(), ancestor_children.next()) {
(Some(left), right) => {
previous_sibling =
left.apply(&element, previous_sibling.as_ref(), right, &env);
left.apply(&element, previous_sibling.as_ref(), right, &parent_scope);
}
(None, Some(ref mut right)) => {
right.detach(&element);