mirror of https://github.com/yewstack/yew
Update yew-shared to 2018 edition
This commit is contained in:
parent
0c5682d07c
commit
b24dc28e20
|
@ -1,14 +1,17 @@
|
||||||
[package]
|
[package]
|
||||||
name = "yew-shared"
|
name = "yew-shared"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
serde = "1.0"
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_derive = "1.0"
|
|
||||||
bincode = "=1.0.1"
|
bincode = "=1.0.1"
|
||||||
anymap = "0.12"
|
anymap = "0.12"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
stdweb = "^0.4.14"
|
stdweb = "^0.4.14"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
yew = { path = "../.." }
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
//! This module contains types to support multi-threading in Yew.
|
//! This module contains types to support multi-threading in Yew.
|
||||||
|
|
||||||
use std::rc::Rc;
|
use crate::callback::Callback;
|
||||||
|
use crate::scheduler::{scheduler, Runnable, Shared};
|
||||||
|
use anymap::{AnyMap, Entry};
|
||||||
|
use bincode;
|
||||||
|
use log::warn;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use slab::Slab;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use serde::{Serialize, Deserialize};
|
use std::rc::Rc;
|
||||||
use bincode;
|
|
||||||
use anymap::{AnyMap, Entry};
|
|
||||||
use slab::Slab;
|
|
||||||
use stdweb::Value;
|
use stdweb::Value;
|
||||||
use scheduler::{Runnable, Shared, scheduler};
|
use stdweb::{_js_impl, js};
|
||||||
use callback::Callback;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum ToWorker<T> {
|
enum ToWorker<T> {
|
||||||
|
@ -19,11 +21,7 @@ enum ToWorker<T> {
|
||||||
Destroy,
|
Destroy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Transferable for ToWorker<T>
|
impl<T> Transferable for ToWorker<T> where T: Serialize + for<'de> Deserialize<'de> {}
|
||||||
where
|
|
||||||
T: Serialize + for <'de> Deserialize<'de>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum FromWorker<T> {
|
enum FromWorker<T> {
|
||||||
|
@ -32,17 +30,12 @@ enum FromWorker<T> {
|
||||||
ProcessOutput(HandlerId, T),
|
ProcessOutput(HandlerId, T),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Transferable for FromWorker<T>
|
impl<T> Transferable for FromWorker<T> where T: Serialize + for<'de> Deserialize<'de> {}
|
||||||
where
|
|
||||||
T: Serialize + for <'de> Deserialize<'de>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Represents a message which you could send to an agent.
|
/// Represents a message which you could send to an agent.
|
||||||
pub trait Transferable
|
pub trait Transferable
|
||||||
where
|
where
|
||||||
Self: Serialize + for <'de> Deserialize<'de>,
|
Self: Serialize + for<'de> Deserialize<'de>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +46,11 @@ trait Packed {
|
||||||
|
|
||||||
impl<T: Transferable> Packed for T {
|
impl<T: Transferable> Packed for T {
|
||||||
fn pack(&self) -> Vec<u8> {
|
fn pack(&self) -> Vec<u8> {
|
||||||
bincode::serialize(&self)
|
bincode::serialize(&self).expect("can't serialize a transferable object")
|
||||||
.expect("can't serialize a transferable object")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unpack(data: &Vec<u8>) -> Self {
|
fn unpack(data: &Vec<u8>) -> Self {
|
||||||
bincode::deserialize(&data)
|
bincode::deserialize(&data).expect("can't deserialize a transferable object")
|
||||||
.expect("can't deserialize a transferable object")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,11 +85,11 @@ pub trait Threaded {
|
||||||
|
|
||||||
impl<T> Threaded for T
|
impl<T> Threaded for T
|
||||||
where
|
where
|
||||||
T: Agent<Reach=Public>,
|
T: Agent<Reach = Public>,
|
||||||
{
|
{
|
||||||
fn register() {
|
fn register() {
|
||||||
let scope = AgentScope::<T>::new();
|
let scope = AgentScope::<T>::new();
|
||||||
let responder = WorkerResponder { };
|
let responder = WorkerResponder {};
|
||||||
let link = AgentLink::connect(&scope, responder);
|
let link = AgentLink::connect(&scope, responder);
|
||||||
let upd = AgentUpdate::Create(link);
|
let upd = AgentUpdate::Create(link);
|
||||||
scope.send(upd);
|
scope.send(upd);
|
||||||
|
@ -108,15 +99,15 @@ where
|
||||||
ToWorker::Connected(id) => {
|
ToWorker::Connected(id) => {
|
||||||
let upd = AgentUpdate::Connected(id);
|
let upd = AgentUpdate::Connected(id);
|
||||||
scope.send(upd);
|
scope.send(upd);
|
||||||
},
|
}
|
||||||
ToWorker::ProcessInput(id, value) => {
|
ToWorker::ProcessInput(id, value) => {
|
||||||
let upd = AgentUpdate::Input(value, id);
|
let upd = AgentUpdate::Input(value, id);
|
||||||
scope.send(upd);
|
scope.send(upd);
|
||||||
},
|
}
|
||||||
ToWorker::Disconnected(id) => {
|
ToWorker::Disconnected(id) => {
|
||||||
let upd = AgentUpdate::Disconnected(id);
|
let upd = AgentUpdate::Disconnected(id);
|
||||||
scope.send(upd);
|
scope.send(upd);
|
||||||
},
|
}
|
||||||
ToWorker::Destroy => {
|
ToWorker::Destroy => {
|
||||||
let upd = AgentUpdate::Destroy;
|
let upd = AgentUpdate::Destroy;
|
||||||
scope.send(upd);
|
scope.send(upd);
|
||||||
|
@ -124,7 +115,7 @@ where
|
||||||
// Terminates web worker
|
// Terminates web worker
|
||||||
self.close();
|
self.close();
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let loaded: FromWorker<T::Output> = FromWorker::WorkerLoaded;
|
let loaded: FromWorker<T::Output> = FromWorker::WorkerLoaded;
|
||||||
|
@ -215,14 +206,16 @@ impl Discoverer for Context {
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
// TODO Insert callback!
|
// TODO Insert callback!
|
||||||
entry.get_mut().create_bridge(callback)
|
entry.get_mut().create_bridge(callback)
|
||||||
},
|
}
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
let scope = AgentScope::<AGN>::new();
|
let scope = AgentScope::<AGN>::new();
|
||||||
let launched = LocalAgent::new(&scope);
|
let launched = LocalAgent::new(&scope);
|
||||||
let responder = SlabResponder { slab: launched.slab() };
|
let responder = SlabResponder {
|
||||||
|
slab: launched.slab(),
|
||||||
|
};
|
||||||
scope_to_init = Some((scope.clone(), responder));
|
scope_to_init = Some((scope.clone(), responder));
|
||||||
entry.insert(launched).create_bridge(callback)
|
entry.insert(launched).create_bridge(callback)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if let Some((scope, responder)) = scope_to_init {
|
if let Some((scope, responder)) = scope_to_init {
|
||||||
|
@ -346,11 +339,11 @@ impl Discoverer for Private {
|
||||||
match msg {
|
match msg {
|
||||||
FromWorker::WorkerLoaded => {
|
FromWorker::WorkerLoaded => {
|
||||||
// TODO Send `Connected` message
|
// TODO Send `Connected` message
|
||||||
},
|
}
|
||||||
FromWorker::ProcessOutput(id, output) => {
|
FromWorker::ProcessOutput(id, output) => {
|
||||||
assert_eq!(id.raw_id(), SINGLETON_ID.raw_id());
|
assert_eq!(id.raw_id(), SINGLETON_ID.raw_id());
|
||||||
callback.emit(output);
|
callback.emit(output);
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// TODO Need somethig better...
|
// TODO Need somethig better...
|
||||||
|
@ -441,7 +434,7 @@ impl Discoverer for Public {
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
// TODO Insert callback!
|
// TODO Insert callback!
|
||||||
entry.get_mut().create_bridge(callback)
|
entry.get_mut().create_bridge(callback)
|
||||||
},
|
}
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
let slab_base: Shared<Slab<Callback<AGN::Output>>> =
|
let slab_base: Shared<Slab<Callback<AGN::Output>>> =
|
||||||
Rc::new(RefCell::new(Slab::new()));
|
Rc::new(RefCell::new(Slab::new()));
|
||||||
|
@ -452,15 +445,18 @@ impl Discoverer for Public {
|
||||||
FromWorker::WorkerLoaded => {
|
FromWorker::WorkerLoaded => {
|
||||||
// TODO Use `AtomicBool` lock to check its loaded
|
// TODO Use `AtomicBool` lock to check its loaded
|
||||||
// TODO Send `Connected` message
|
// TODO Send `Connected` message
|
||||||
},
|
}
|
||||||
FromWorker::ProcessOutput(id, output) => {
|
FromWorker::ProcessOutput(id, output) => {
|
||||||
let callback = slab.borrow().get(id.raw_id()).cloned();
|
let callback = slab.borrow().get(id.raw_id()).cloned();
|
||||||
if let Some(callback) = callback {
|
if let Some(callback) = callback {
|
||||||
callback.emit(output);
|
callback.emit(output);
|
||||||
} else {
|
} else {
|
||||||
warn!("Id of handler for remote worker not exists <slab>: {}", id.raw_id());
|
warn!(
|
||||||
|
"Id of handler for remote worker not exists <slab>: {}",
|
||||||
|
id.raw_id()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let name_of_resource = AGN::name_of_resource();
|
let name_of_resource = AGN::name_of_resource();
|
||||||
|
@ -474,7 +470,7 @@ impl Discoverer for Public {
|
||||||
};
|
};
|
||||||
let launched = RemoteAgent::new(&worker, slab_base);
|
let launched = RemoteAgent::new(&worker, slab_base);
|
||||||
entry.insert(launched).create_bridge(callback)
|
entry.insert(launched).create_bridge(callback)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Box::new(bridge)
|
Box::new(bridge)
|
||||||
|
@ -531,11 +527,10 @@ impl<AGN: Agent> Drop for PublicBridge<AGN> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a single instance in a browser.
|
/// Create a single instance in a browser.
|
||||||
pub struct Global;
|
pub struct Global;
|
||||||
|
|
||||||
impl Discoverer for Global { }
|
impl Discoverer for Global {}
|
||||||
|
|
||||||
/// Declares the behavior of the agent.
|
/// Declares the behavior of the agent.
|
||||||
pub trait Agent: Sized + 'static {
|
pub trait Agent: Sized + 'static {
|
||||||
|
@ -555,22 +550,22 @@ pub trait Agent: Sized + 'static {
|
||||||
fn update(&mut self, msg: Self::Message);
|
fn update(&mut self, msg: Self::Message);
|
||||||
|
|
||||||
/// This method called on when a new bridge created.
|
/// This method called on when a new bridge created.
|
||||||
fn connected(&mut self, _id: HandlerId) { }
|
fn connected(&mut self, _id: HandlerId) {}
|
||||||
|
|
||||||
/// This method called on every incoming message.
|
/// This method called on every incoming message.
|
||||||
fn handle(&mut self, msg: Self::Input, id: HandlerId);
|
fn handle(&mut self, msg: Self::Input, id: HandlerId);
|
||||||
|
|
||||||
/// This method called on when a new bridge destroyed.
|
/// This method called on when a new bridge destroyed.
|
||||||
fn disconnected(&mut self, _id: HandlerId) { }
|
fn disconnected(&mut self, _id: HandlerId) {}
|
||||||
|
|
||||||
/// Creates an instance of an agent.
|
/// Creates an instance of an agent.
|
||||||
fn destroy(&mut self) { }
|
fn destroy(&mut self) {}
|
||||||
|
|
||||||
/// Represents the name of loading resorce for remote workers which
|
/// Represents the name of loading resorce for remote workers which
|
||||||
/// have to live in a separate files.
|
/// have to live in a separate files.
|
||||||
fn name_of_resource() -> &'static str { "main.js" }
|
fn name_of_resource() -> &'static str {
|
||||||
|
"main.js"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This sctruct holds a reference to a component and to a global scheduler.
|
/// This sctruct holds a reference to a component and to a global scheduler.
|
||||||
|
@ -606,8 +601,7 @@ trait Responder<AGN: Agent> {
|
||||||
fn response(&self, id: HandlerId, output: AGN::Output);
|
fn response(&self, id: HandlerId, output: AGN::Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WorkerResponder {
|
struct WorkerResponder {}
|
||||||
}
|
|
||||||
|
|
||||||
impl<AGN: Agent> Responder<AGN> for WorkerResponder {
|
impl<AGN: Agent> Responder<AGN> for WorkerResponder {
|
||||||
fn response(&self, id: HandlerId, output: AGN::Output) {
|
fn response(&self, id: HandlerId, output: AGN::Output) {
|
||||||
|
@ -702,27 +696,33 @@ where
|
||||||
this.agent = Some(AGN::create(env));
|
this.agent = Some(AGN::create(env));
|
||||||
}
|
}
|
||||||
AgentUpdate::Message(msg) => {
|
AgentUpdate::Message(msg) => {
|
||||||
this.agent.as_mut()
|
this.agent
|
||||||
|
.as_mut()
|
||||||
.expect("agent was not created to process messages")
|
.expect("agent was not created to process messages")
|
||||||
.update(msg);
|
.update(msg);
|
||||||
}
|
}
|
||||||
AgentUpdate::Connected(id) => {
|
AgentUpdate::Connected(id) => {
|
||||||
this.agent.as_mut()
|
this.agent
|
||||||
|
.as_mut()
|
||||||
.expect("agent was not created to send a connected message")
|
.expect("agent was not created to send a connected message")
|
||||||
.connected(id);
|
.connected(id);
|
||||||
}
|
}
|
||||||
AgentUpdate::Input(inp, id) => {
|
AgentUpdate::Input(inp, id) => {
|
||||||
this.agent.as_mut()
|
this.agent
|
||||||
|
.as_mut()
|
||||||
.expect("agent was not created to process inputs")
|
.expect("agent was not created to process inputs")
|
||||||
.handle(inp, id);
|
.handle(inp, id);
|
||||||
}
|
}
|
||||||
AgentUpdate::Disconnected(id) => {
|
AgentUpdate::Disconnected(id) => {
|
||||||
this.agent.as_mut()
|
this.agent
|
||||||
|
.as_mut()
|
||||||
.expect("agent was not created to send a disconnected message")
|
.expect("agent was not created to send a disconnected message")
|
||||||
.disconnected(id);
|
.disconnected(id);
|
||||||
}
|
}
|
||||||
AgentUpdate::Destroy => {
|
AgentUpdate::Destroy => {
|
||||||
let mut agent = this.agent.take()
|
let mut agent = this
|
||||||
|
.agent
|
||||||
|
.take()
|
||||||
.expect("trying to destroy not existent agent");
|
.expect("trying to destroy not existent agent");
|
||||||
agent.destroy();
|
agent.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! This module contains `App` sctruct which used to bootstrap
|
//! This module contains `App` sctruct which used to bootstrap
|
||||||
//! a component in an isolated scope.
|
//! a component in an isolated scope.
|
||||||
|
|
||||||
|
use crate::html::{Component, Renderable, Scope};
|
||||||
use stdweb::web::{document, Element, INode, IParentNode};
|
use stdweb::web::{document, Element, INode, IParentNode};
|
||||||
use html::{Scope, Component, Renderable};
|
|
||||||
|
|
||||||
/// An application instance.
|
/// An application instance.
|
||||||
pub struct App<COMP: Component> {
|
pub struct App<COMP: Component> {
|
||||||
|
@ -46,4 +46,3 @@ fn clear_element(element: &Element) {
|
||||||
element.remove_child(&child).expect("can't remove a child");
|
element.remove_child(&child).expect("can't remove a child");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
//! Also this module contains declaration of `Component` trait which used
|
//! Also this module contains declaration of `Component` trait which used
|
||||||
//! to create own UI-components.
|
//! to create own UI-components.
|
||||||
|
|
||||||
use std::rc::Rc;
|
use crate::callback::Callback;
|
||||||
|
use crate::scheduler::{scheduler, Runnable, Shared};
|
||||||
|
use crate::virtual_dom::{Listener, VDiff, VNode};
|
||||||
|
use log::debug;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use stdweb::web::{Element, EventListenerHandle, FileList, INode, Node};
|
use std::rc::Rc;
|
||||||
use stdweb::web::html_element::SelectElement;
|
use stdweb::web::html_element::SelectElement;
|
||||||
use virtual_dom::{Listener, VDiff, VNode};
|
use stdweb::web::{Element, EventListenerHandle, FileList, INode, Node};
|
||||||
use callback::Callback;
|
use stdweb::{_js_impl, js};
|
||||||
use scheduler::{Runnable, Shared, scheduler};
|
|
||||||
|
|
||||||
/// This type indicates that component should be rendered again.
|
/// This type indicates that component should be rendered again.
|
||||||
pub type ShouldRender = bool;
|
pub type ShouldRender = bool;
|
||||||
|
@ -33,7 +35,7 @@ pub trait Component: Sized + 'static {
|
||||||
unimplemented!("you should implement `change` method for a component with properties")
|
unimplemented!("you should implement `change` method for a component with properties")
|
||||||
}
|
}
|
||||||
/// Called for finalization on the final point of the component's lifetime.
|
/// Called for finalization on the final point of the component's lifetime.
|
||||||
fn destroy(&mut self) { } // TODO Replace with `Drop`
|
fn destroy(&mut self) {} // TODO Replace with `Drop`
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should be rendered relative to context and component environment.
|
/// Should be rendered relative to context and component environment.
|
||||||
|
@ -43,7 +45,7 @@ pub trait Renderable<COMP: Component> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update message for a `Components` instance. Used by scope sender.
|
/// Update message for a `Components` instance. Used by scope sender.
|
||||||
pub(crate) enum ComponentUpdate< COMP: Component> {
|
pub(crate) enum ComponentUpdate<COMP: Component> {
|
||||||
/// Creating an instance of the component
|
/// Creating an instance of the component
|
||||||
Create(ComponentLink<COMP>),
|
Create(ComponentLink<COMP>),
|
||||||
/// Wraps messages for a component.
|
/// Wraps messages for a component.
|
||||||
|
@ -195,7 +197,10 @@ where
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut should_update = false;
|
let mut should_update = false;
|
||||||
let upd = self.message.take().expect("component's envelope called twice");
|
let upd = self
|
||||||
|
.message
|
||||||
|
.take()
|
||||||
|
.expect("component's envelope called twice");
|
||||||
// This loop pops one item, because the following
|
// This loop pops one item, because the following
|
||||||
// updates could try to borrow the same cell
|
// updates could try to borrow the same cell
|
||||||
// Important! Don't use `while let` here, because it
|
// Important! Don't use `while let` here, because it
|
||||||
|
@ -209,35 +214,44 @@ where
|
||||||
let current_frame = this.component.as_ref().unwrap().view();
|
let current_frame = this.component.as_ref().unwrap().view();
|
||||||
this.last_frame = Some(current_frame);
|
this.last_frame = Some(current_frame);
|
||||||
// First-time rendering the tree
|
// First-time rendering the tree
|
||||||
let node = this.last_frame.as_mut()
|
let node = this.last_frame.as_mut().unwrap().apply(
|
||||||
.unwrap()
|
this.element.as_node(),
|
||||||
.apply(this.element.as_node(), None, this.ancestor.take(), &env);
|
None,
|
||||||
|
this.ancestor.take(),
|
||||||
|
&env,
|
||||||
|
);
|
||||||
if let Some(ref mut cell) = this.occupied {
|
if let Some(ref mut cell) = this.occupied {
|
||||||
*cell.borrow_mut() = node;
|
*cell.borrow_mut() = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ComponentUpdate::Message(msg) => {
|
ComponentUpdate::Message(msg) => {
|
||||||
should_update |= this.component.as_mut()
|
should_update |= this
|
||||||
|
.component
|
||||||
|
.as_mut()
|
||||||
.expect("component was not created to process messages")
|
.expect("component was not created to process messages")
|
||||||
.update(msg);
|
.update(msg);
|
||||||
}
|
}
|
||||||
ComponentUpdate::Properties(props) => {
|
ComponentUpdate::Properties(props) => {
|
||||||
should_update |= this.component.as_mut()
|
should_update |= this
|
||||||
|
.component
|
||||||
|
.as_mut()
|
||||||
.expect("component was not created to process properties")
|
.expect("component was not created to process properties")
|
||||||
.change(props);
|
.change(props);
|
||||||
}
|
}
|
||||||
ComponentUpdate::Destroy => {
|
ComponentUpdate::Destroy => {
|
||||||
// TODO this.component.take() instead of destroyed
|
// TODO this.component.take() instead of destroyed
|
||||||
this.component.as_mut().unwrap().destroy();
|
this.component.as_mut().unwrap().destroy();
|
||||||
this.last_frame.as_mut().unwrap().detach(this.element.as_node());
|
this.last_frame
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.detach(this.element.as_node());
|
||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if should_update {
|
if should_update {
|
||||||
let mut next_frame = this.component.as_ref().unwrap().view();
|
let mut next_frame = this.component.as_ref().unwrap().view();
|
||||||
// Re-rendering the tree
|
// Re-rendering the tree
|
||||||
let node =
|
let node = next_frame.apply(this.element.as_node(), None, this.last_frame.take(), &env);
|
||||||
next_frame.apply(this.element.as_node(), None, this.last_frame.take(), &env);
|
|
||||||
if let Some(ref mut cell) = this.occupied {
|
if let Some(ref mut cell) = this.occupied {
|
||||||
*cell.borrow_mut() = node;
|
*cell.borrow_mut() = node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,3 @@
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
extern crate serde;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
extern crate anymap;
|
|
||||||
extern crate bincode;
|
|
||||||
extern crate slab;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate stdweb;
|
|
||||||
|
|
||||||
pub mod agent;
|
pub mod agent;
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod callback;
|
pub mod callback;
|
||||||
|
@ -18,7 +7,7 @@ pub mod virtual_dom;
|
||||||
|
|
||||||
/// The module that contains all events available in the framework.
|
/// The module that contains all events available in the framework.
|
||||||
pub mod events {
|
pub mod events {
|
||||||
pub use html::{ChangeData, InputData};
|
pub use crate::html::{ChangeData, InputData};
|
||||||
|
|
||||||
pub use stdweb::web::event::{
|
pub use stdweb::web::event::{
|
||||||
BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent,
|
BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent,
|
||||||
|
@ -33,19 +22,15 @@ pub mod events {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use html::{Component, ComponentLink, Href, Html, Renderable, ShouldRender};
|
pub use crate::agent::{Bridge, Bridged, Threaded};
|
||||||
|
pub use crate::app::App;
|
||||||
pub use app::App;
|
pub use crate::callback::Callback;
|
||||||
|
pub use crate::events::*;
|
||||||
pub use callback::Callback;
|
pub use crate::html::{Component, ComponentLink, Href, Html, Renderable, ShouldRender};
|
||||||
|
|
||||||
pub use agent::{Bridge, Bridged, Threaded};
|
|
||||||
|
|
||||||
pub use events::*;
|
|
||||||
|
|
||||||
/// Prelude module for creating worker.
|
/// Prelude module for creating worker.
|
||||||
pub mod worker {
|
pub mod worker {
|
||||||
pub use agent::{
|
pub use crate::agent::{
|
||||||
Agent, AgentLink, Bridge, Bridged, Context, Global, HandlerId, Job, Private, Public,
|
Agent, AgentLink, Bridge, Bridged, Context, Global, HandlerId, Job, Private, Public,
|
||||||
Transferable,
|
Transferable,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! This module contains a scheduler.
|
//! This module contains a scheduler.
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
pub(crate) type Shared<T> = Rc<RefCell<T>>;
|
pub(crate) type Shared<T> = Rc<RefCell<T>>;
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub use self::vlist::VList;
|
||||||
pub use self::vnode::VNode;
|
pub use self::vnode::VNode;
|
||||||
pub use self::vtag::VTag;
|
pub use self::vtag::VTag;
|
||||||
pub use self::vtext::VText;
|
pub use self::vtext::VText;
|
||||||
use html::{Component, Scope};
|
use crate::html::{Component, Scope};
|
||||||
|
|
||||||
/// `Listener` trait is an universal implementation of an event listener
|
/// `Listener` trait is an universal implementation of an event listener
|
||||||
/// which helps to bind Rust-listener to JS-listener (DOM).
|
/// which helps to bind Rust-listener to JS-listener (DOM).
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
//! This module contains the implementation of a virtual component `VComp`.
|
//! This module contains the implementation of a virtual component `VComp`.
|
||||||
|
|
||||||
|
use super::{Reform, VDiff, VNode};
|
||||||
|
use crate::callback::Callback;
|
||||||
|
use crate::html::{Component, ComponentUpdate, NodeCell, Renderable, Scope};
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use stdweb::unstable::TryInto;
|
use stdweb::unstable::TryInto;
|
||||||
use stdweb::web::{document, Element, INode, Node};
|
use stdweb::web::{document, Element, INode, Node};
|
||||||
use html::{Component, ComponentUpdate, Scope, NodeCell, Renderable};
|
|
||||||
use callback::Callback;
|
|
||||||
use super::{Reform, VDiff, VNode};
|
|
||||||
|
|
||||||
struct Hidden;
|
struct Hidden;
|
||||||
|
|
||||||
|
@ -79,7 +79,8 @@ impl<COMP: Component> VComp<COMP> {
|
||||||
// Ignore update till properties changed
|
// Ignore update till properties changed
|
||||||
if previous_props != new_props {
|
if previous_props != new_props {
|
||||||
let props = new_props.as_ref().unwrap().clone();
|
let props = new_props.as_ref().unwrap().clone();
|
||||||
lazy_activator.borrow_mut()
|
lazy_activator
|
||||||
|
.borrow_mut()
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("activator for child scope was not set (blind sender)")
|
.expect("activator for child scope was not set (blind sender)")
|
||||||
.send(ComponentUpdate::Properties(props));
|
.send(ComponentUpdate::Properties(props));
|
||||||
|
@ -90,7 +91,8 @@ impl<COMP: Component> VComp<COMP> {
|
||||||
let destroyer = {
|
let destroyer = {
|
||||||
let lazy_activator = lazy_activator;
|
let lazy_activator = lazy_activator;
|
||||||
move || {
|
move || {
|
||||||
lazy_activator.borrow_mut()
|
lazy_activator
|
||||||
|
.borrow_mut()
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("activator for child scope was not set (destroyer)")
|
.expect("activator for child scope was not set (destroyer)")
|
||||||
.send(ComponentUpdate::Destroy);
|
.send(ComponentUpdate::Destroy);
|
||||||
|
@ -229,7 +231,8 @@ where
|
||||||
fn detach(&mut self, parent: &Node) -> Option<Node> {
|
fn detach(&mut self, parent: &Node) -> Option<Node> {
|
||||||
// Destroy the loop. It's impossible to use `Drop`,
|
// Destroy the loop. It's impossible to use `Drop`,
|
||||||
// because parts can be reused with `grab_sender_of`.
|
// because parts can be reused with `grab_sender_of`.
|
||||||
(self.destroyer)(); // TODO Chech it works
|
(self.destroyer)(); // TODO Check it works
|
||||||
|
|
||||||
// Keep the sibling in the cell and send a message `Drop` to a loop
|
// Keep the sibling in the cell and send a message `Drop` to a loop
|
||||||
self.cell.borrow_mut().take().and_then(|node| {
|
self.cell.borrow_mut().take().and_then(|node| {
|
||||||
let sibling = node.next_sibling();
|
let sibling = node.next_sibling();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! This module contains fragments implementation.
|
//! This module contains fragments implementation.
|
||||||
use super::{VDiff, VNode, VText};
|
use super::{VDiff, VNode, VText};
|
||||||
use html::{Component, Scope};
|
use crate::html::{Component, Scope};
|
||||||
use stdweb::web::Node;
|
use stdweb::web::Node;
|
||||||
|
|
||||||
/// This struct represents a fragment of the Virtual DOM tree.
|
/// This struct represents a fragment of the Virtual DOM tree.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! This module contains the implementation of abstract virtual node.
|
//! This module contains the implementation of abstract virtual node.
|
||||||
|
|
||||||
use super::{VComp, VDiff, VList, VTag, VText};
|
use super::{VComp, VDiff, VList, VTag, VText};
|
||||||
use html::{Component, Renderable, Scope};
|
use crate::html::{Component, Renderable, Scope};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use stdweb::web::{INode, Node};
|
use stdweb::web::{INode, Node};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//! This module contains the implementation of a virtual element node `VTag`.
|
//! This module contains the implementation of a virtual element node `VTag`.
|
||||||
|
|
||||||
use super::{Attributes, Classes, Listener, Listeners, Patch, Reform, VDiff, VNode};
|
use super::{Attributes, Classes, Listener, Listeners, Patch, Reform, VDiff, VNode};
|
||||||
use html::{Component, Scope};
|
use crate::html::{Component, Scope};
|
||||||
|
use log::warn;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -10,6 +11,7 @@ use stdweb::unstable::TryFrom;
|
||||||
use stdweb::web::html_element::InputElement;
|
use stdweb::web::html_element::InputElement;
|
||||||
use stdweb::web::html_element::TextAreaElement;
|
use stdweb::web::html_element::TextAreaElement;
|
||||||
use stdweb::web::{document, Element, EventListenerHandle, IElement, INode, Node};
|
use stdweb::web::{document, Element, EventListenerHandle, IElement, INode, Node};
|
||||||
|
use stdweb::{_js_impl, js};
|
||||||
|
|
||||||
/// A type for a virtual
|
/// A type for a virtual
|
||||||
/// [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)
|
/// [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//! This module contains the implementation of a virtual text node `VText`.
|
//! This module contains the implementation of a virtual text node `VText`.
|
||||||
|
|
||||||
|
use super::{Reform, VDiff, VNode};
|
||||||
|
use crate::html::{Component, Scope};
|
||||||
|
use log::warn;
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use stdweb::web::{document, INode, Node, TextNode};
|
use stdweb::web::{document, INode, Node, TextNode};
|
||||||
use html::{Component, Scope};
|
|
||||||
use super::{Reform, VDiff, VNode};
|
|
||||||
|
|
||||||
/// A type for a virtual
|
/// A type for a virtual
|
||||||
/// [`TextNode`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode)
|
/// [`TextNode`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode)
|
||||||
|
@ -34,7 +35,9 @@ impl<COMP: Component> VDiff for VText<COMP> {
|
||||||
|
|
||||||
/// Remove VTag from parent.
|
/// Remove VTag from parent.
|
||||||
fn detach(&mut self, parent: &Node) -> Option<Node> {
|
fn detach(&mut self, parent: &Node) -> Option<Node> {
|
||||||
let node = self.reference.take()
|
let node = self
|
||||||
|
.reference
|
||||||
|
.take()
|
||||||
.expect("tried to remove not rendered VText from DOM");
|
.expect("tried to remove not rendered VText from DOM");
|
||||||
let sibling = node.next_sibling();
|
let sibling = node.next_sibling();
|
||||||
if parent.remove_child(&node).is_err() {
|
if parent.remove_child(&node).is_err() {
|
||||||
|
@ -54,7 +57,10 @@ impl<COMP: Component> VDiff for VText<COMP> {
|
||||||
opposite: Option<VNode<Self::Component>>,
|
opposite: Option<VNode<Self::Component>>,
|
||||||
_: &Scope<Self::Component>,
|
_: &Scope<Self::Component>,
|
||||||
) -> Option<Node> {
|
) -> Option<Node> {
|
||||||
assert!(self.reference.is_none(), "reference is ignored so must not be set");
|
assert!(
|
||||||
|
self.reference.is_none(),
|
||||||
|
"reference is ignored so must not be set"
|
||||||
|
);
|
||||||
let reform = {
|
let reform = {
|
||||||
match opposite {
|
match opposite {
|
||||||
// If element matched this type
|
// If element matched this type
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
extern crate yew;
|
|
||||||
|
|
||||||
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
|
||||||
use yew::virtual_dom::VNode;
|
use yew::virtual_dom::VNode;
|
||||||
|
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
||||||
|
|
||||||
struct Comp;
|
struct Comp;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
extern crate yew;
|
|
||||||
|
|
||||||
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
|
||||||
use yew::virtual_dom::VNode;
|
use yew::virtual_dom::VNode;
|
||||||
|
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
||||||
|
|
||||||
struct Comp;
|
struct Comp;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
extern crate yew;
|
|
||||||
|
|
||||||
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
|
||||||
use yew::virtual_dom::VNode;
|
use yew::virtual_dom::VNode;
|
||||||
|
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
||||||
|
|
||||||
struct Comp;
|
struct Comp;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
extern crate yew;
|
|
||||||
|
|
||||||
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
|
||||||
use yew::virtual_dom::VNode;
|
use yew::virtual_dom::VNode;
|
||||||
|
use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};
|
||||||
|
|
||||||
struct Comp;
|
struct Comp;
|
||||||
|
|
||||||
|
@ -30,4 +28,3 @@ fn text_as_root() {
|
||||||
{ "Text Node As Root" }
|
{ "Text Node As Root" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
web_logger = "0.1"
|
web_logger = "0.1"
|
||||||
serde = "1.0"
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_derive = "1.0"
|
|
||||||
yew = { path = "../.." }
|
yew = { path = "../.." }
|
||||||
stdweb = "0.4"
|
stdweb = "0.4"
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
//! Agent that exposes a usable routing interface to components.
|
//! Agent that exposes a usable routing interface to components.
|
||||||
|
|
||||||
use crate::routing::RouteService;
|
use crate::routing::RouteService;
|
||||||
use yew::worker::*;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use stdweb::Value;
|
|
||||||
use stdweb::JsSerialize;
|
|
||||||
use stdweb::unstable::TryFrom;
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use stdweb::JsSerialize;
|
||||||
|
use stdweb::Value;
|
||||||
|
use stdweb::unstable::TryFrom;
|
||||||
|
use yew::worker::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize) ]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize) ]
|
||||||
pub struct Route<T> {
|
pub struct Route<T> {
|
||||||
|
|
Loading…
Reference in New Issue