Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move yew-agent to gloo #2326

Merged
merged 4 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion examples/web_worker_fib/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::rc::Rc;
use crate::agent::{Worker, WorkerInput, WorkerOutput};

use web_sys::HtmlInputElement;
Expand All @@ -22,7 +23,11 @@ impl Component for Model {
type Properties = ();

fn create(ctx: &Context<Self>) -> Self {
let worker = Worker::bridge(ctx.link().callback(Self::Message::WorkerMsg));
let cb = {
let link = ctx.link().clone();
move |e| link.send_message(Self::Message::WorkerMsg(e))
};
let worker = Worker::bridge(Rc::new(cb));

Self {
clicker_value: 0,
Expand Down
24 changes: 1 addition & 23 deletions packages/yew-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,6 @@ readme = "../../README.md"
description = "Agents for Yew"
license = "MIT OR Apache-2.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anymap2 = "0.13"
bincode = "1"
gloo-console = "0.2"
gloo-utils = "0.1"
js-sys = "0.3"
serde = { version = "1", features = ["derive"] }
slab = "0.4"
wasm-bindgen = "0.2"
yew = { version = "0.19.3", path = "../yew" }
wasm-bindgen-futures = "0.4"

[dependencies.web-sys]
version = "0.3"
features = [
"Blob",
"BlobPropertyBag",
"DedicatedWorkerGlobalScope",
"MessageEvent",
"Url",
"Worker",
"WorkerOptions",
]
gloo-worker = { path = "../../../gloo/crates/worker" }
20 changes: 11 additions & 9 deletions packages/yew-agent/src/hooks.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::cell::RefCell;
use std::rc::Rc;

use crate::*;
use yew::prelude::*;
use crate::*;

/// State handle for [`use_bridge`] hook
pub struct UseBridgeHandle<T>
Expand All @@ -16,16 +16,16 @@ impl<T> UseBridgeHandle<T>
where
T: Bridged,
{
/// Send a message to an agent.
/// Send a message to an worker.
pub fn send(&self, msg: T::Input) {
let mut bridge = self.inner.borrow_mut();
bridge.send(msg);
}
}

/// A hook to bridge to an Agent.
/// A hook to bridge to an [`Worker`].
///
/// This hooks will only bridge the agent once over the entire component lifecycle.
/// This hooks will only bridge the worker once over the entire component lifecycle.
///
/// Takes a callback as the only argument. The callback will be updated on every render to make
/// sure captured values (if any) are up to date.
Expand All @@ -46,16 +46,18 @@ where
}

let bridge = use_mut_ref(move || {
T::bridge(Callback::from(move |output| {
let on_output = on_output_ref.borrow().clone();
on_output(output);
}))
T::bridge({
Rc::new(move |output| {
let on_output = on_output_ref.borrow().clone();
on_output(output);
})
})
});

UseBridgeHandle { inner: bridge }
}

impl<T: Agent> Clone for UseBridgeHandle<T> {
impl<T: Worker> Clone for UseBridgeHandle<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
Expand Down
116 changes: 2 additions & 114 deletions packages/yew-agent/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,119 +1,7 @@
//! This module contains Yew's web worker implementation.

mod hooks;
mod link;
mod pool;
mod worker;

pub use hooks::{use_bridge, UseBridgeHandle};
pub use link::AgentLink;
pub(crate) use link::*;
pub(crate) use pool::*;
pub use pool::{Dispatched, Dispatcher};
pub use worker::{Private, PrivateAgent, Public, PublicAgent};

use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::{Deref, DerefMut};
use yew::callback::Callback;

/// Declares the behavior of the agent.
pub trait Agent: Sized + 'static {
/// Reach capability of the agent.
type Reach: Discoverer<Agent = Self>;
/// Type of an input message.
type Message;
/// Incoming message type.
type Input;
/// Outgoing message type.
type Output;

/// Creates an instance of an agent.
fn create(link: AgentLink<Self>) -> Self;

/// This method called on every update message.
fn update(&mut self, msg: Self::Message);

/// This method called on when a new bridge created.
fn connected(&mut self, _id: HandlerId) {}

/// This method called on every incoming message.
fn handle_input(&mut self, msg: Self::Input, id: HandlerId);

/// This method called on when a new bridge destroyed.
fn disconnected(&mut self, _id: HandlerId) {}

/// This method called when the agent is destroyed.
fn destroy(&mut self) {}

/// Represents the name of loading resorce for remote workers which
/// have to live in a separate files.
fn name_of_resource() -> &'static str {
"main.js"
}

/// Indicates whether the name of the resource is relative.
///
/// The default implementation returns `false`, which will cause the result
/// returned by [`Self::name_of_resource`] to be interpreted as an absolute
/// URL. If `true` is returned, it will be interpreted as a relative URL.
fn resource_path_is_relative() -> bool {
false
}

/// Signifies if resource is a module.
/// This has pending browser support.
fn is_module() -> bool {
false
}
}

/// Id of responses handler.
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Clone, Copy)]
pub struct HandlerId(usize, bool);

impl HandlerId {
fn new(id: usize, respondable: bool) -> Self {
HandlerId(id, respondable)
}
fn raw_id(self) -> usize {
self.0
}
/// Indicates if a handler id corresponds to callback in the Agent runtime.
pub fn is_respondable(self) -> bool {
self.1
}
}

/// Determine a visibility of an agent.
#[doc(hidden)]
pub trait Discoverer {
type Agent: Agent;

/// Spawns an agent and returns `Bridge` implementation.
fn spawn_or_join(
_callback: Option<Callback<<Self::Agent as Agent>::Output>>,
) -> Box<dyn Bridge<Self::Agent>>;
}

/// Bridge to a specific kind of worker.
pub trait Bridge<AGN: Agent> {
/// Send a message to an agent.
fn send(&mut self, msg: AGN::Input);
}

/// This trait allows registering or getting the address of a worker.
pub trait Bridged: Agent + Sized + 'static {
/// Creates a messaging bridge between a worker and the component.
fn bridge(callback: Callback<Self::Output>) -> Box<dyn Bridge<Self>>;
}

impl<T> Bridged for T
where
T: Agent,
<T as Agent>::Reach: Discoverer<Agent = T>,
{
fn bridge(callback: Callback<Self::Output>) -> Box<dyn Bridge<Self>> {
Self::Reach::spawn_or_join(Some(callback))
}
}
#[doc(inline)]
pub use gloo_worker::*;
Loading