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

web-sys services conversion #827

Merged
merged 11 commits into from Jan 15, 2020
98 changes: 79 additions & 19 deletions src/services/console.rs
@@ -1,7 +1,16 @@
//! This module contains a service implementation to use browser's console.

#[allow(unused_imports)]
use stdweb::{_js_impl, js};
use cfg_if::cfg_if;
use cfg_match::cfg_match;
cfg_if! {
if #[cfg(feature = "std_web")] {
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
} else if #[cfg(feature = "web_sys")] {
use wasm_bindgen::JsValue;
use web_sys::console;
}
}

/// A service to use methods of a
/// [Console](https://developer.mozilla.org/en-US/docs/Web/API/Console).
Expand All @@ -17,101 +26,152 @@ impl ConsoleService {
/// [console.log](https://developer.mozilla.org/en-US/docs/Web/API/Console/log)
/// method implementation.
pub fn log(&mut self, message: &str) {
js! { @(no_return) console.log(@{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.log(@{message}); },
feature = "web_sys" => console::log_1(&JsValue::from_str(message)),
};
}

/// [console.warn](https://developer.mozilla.org/en-US/docs/Web/API/Console/warn)
/// method implementation.
pub fn warn(&mut self, message: &str) {
js! { @(no_return) console.warn(@{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.warn(@{message}); },
feature = "web_sys" => console::warn_1(&JsValue::from_str(message)),
};
}

/// [console.info](https://developer.mozilla.org/en-US/docs/Web/API/Console/info)
/// method implementation.
pub fn info(&mut self, message: &str) {
js! { @(no_return) console.info(@{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.info(@{message}); },
feature = "web_sys" => console::info_1(&JsValue::from_str(message)),
};
}

/// [console.error](https://developer.mozilla.org/en-US/docs/Web/API/Console/error)
/// method implementation.
pub fn error(&mut self, message: &str) {
js! { @(no_return) console.error(@{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.error(@{message}); },
feature = "web_sys" => console::error_1(&JsValue::from_str(message)),
};
}

/// [console.debug](https://developer.mozilla.org/en-US/docs/Web/API/Console/debug)
/// method implementation.
pub fn debug(&mut self, message: &str) {
js! { @(no_return) console.debug(@{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.debug(@{message}); },
feature = "web_sys" => console::debug_1(&JsValue::from_str(message)),
};
}

/// [console.count_named](https://developer.mozilla.org/en-US/docs/Web/API/Console/count_named)
/// method implementation.
pub fn count_named(&mut self, name: &str) {
js! { @(no_return) console.count(@{name}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.count(@{name}); },
feature = "web_sys" => console::count_with_label(name),
};
}

/// [console.count](https://developer.mozilla.org/en-US/docs/Web/API/Console/count)
/// method implementation.
pub fn count(&mut self) {
js! { @(no_return) console.count(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.count(); },
feature = "web_sys" => console::count(),
};
}

/// [console.time_named](https://developer.mozilla.org/en-US/docs/Web/API/Console/time_named)
/// method implementation.
pub fn time_named(&mut self, name: &str) {
js! { @(no_return) console.time(@{name}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.time(@{name}); },
feature = "web_sys" => console::time_with_label(name),
};
}

/// [console.time_named_end](https://developer.mozilla.org/en-US/docs/Web/API/Console/time_named_end)
/// method implementation.
pub fn time_named_end(&mut self, name: &str) {
js! { @(no_return) console.timeEnd(@{name}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.timeEnd(@{name}); },
feature = "web_sys" => console::time_end_with_label(name),
};
}

/// [console.time](https://developer.mozilla.org/en-US/docs/Web/API/Console/time)
/// method implementation.
pub fn time(&mut self) {
js! { @(no_return) console.time(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.time(); },
feature = "web_sys" => console::time(),
};
}
/// [console.time_end](https://developer.mozilla.org/en-US/docs/Web/API/Console/time_end)
/// method implementation.
pub fn time_end(&mut self) {
js! { @(no_return) console.timeEnd(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.timeEnd(); },
feature = "web_sys" => console::time_end(),
};
}

/// [console.clear](https://developer.mozilla.org/en-US/docs/Web/API/Console/clear)
/// method implementation.
pub fn clear(&mut self) {
js! { @(no_return) console.clear(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.clear(); },
feature = "web_sys" => console::clear(),
};
}

/// [console.group](https://developer.mozilla.org/en-US/docs/Web/API/Console/group)
/// method implementation.
pub fn group(&mut self) {
js! { @(no_return) console.group(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.group(); },
feature = "web_sys" => console::group_0(),
};
}

/// [console.group_collapsed](https://developer.mozilla.org/en-US/docs/Web/API/Console/group_collapsed)
/// method implementation.
pub fn group_collapsed(&mut self) {
js! { @(no_return) console.groupCollapsed(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.groupCollapsed(); },
feature = "web_sys" => console::group_collapsed_0(),
};
}

/// [console.group_end](https://developer.mozilla.org/en-US/docs/Web/API/Console/group_end)
/// method implementation.
pub fn group_end(&mut self) {
js! { @(no_return) console.groupEnd(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.groupEnd(); },
feature = "web_sys" => console::group_end(),
};
}

/// [console.trace](https://developer.mozilla.org/en-US/docs/Web/API/Console/trace)
/// method implementation.
pub fn trace(&mut self) {
js! { @(no_return) console.trace(); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.trace(); },
feature = "web_sys" => console::trace_0(),
};
}

/// [console.assert](https://developer.mozilla.org/en-US/docs/Web/API/Console/assert)
/// method implementation.
pub fn assert(&mut self, condition: bool, message: &str) {
js! { @(no_return) console.assert(@{condition}, @{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) console.assert(@{condition}, @{message}); },
feature = "web_sys" => console::assert_with_condition_and_data_1(condition, &String::from(message).into()),
};
}
}
32 changes: 24 additions & 8 deletions src/services/dialog.rs
@@ -1,9 +1,17 @@
//! This module contains the implementation of a service
//! to show alerts and confirm dialogs in a browser.

use stdweb::Value;
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
use cfg_if::cfg_if;
use cfg_match::cfg_match;
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::Value;
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
} else if #[cfg(feature = "web_sys")] {
use crate::utils;
}
}

/// A dialog service.
#[derive(Default, Debug)]
Expand All @@ -18,16 +26,24 @@ impl DialogService {
/// Calls [alert](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert)
/// function.
pub fn alert(&mut self, message: &str) {
js! { @(no_return) alert(@{message}); }
cfg_match! {
feature = "std_web" => js! { @(no_return) alert(@{message}); },
feature = "web_sys" => utils::window().alert_with_message(message).unwrap(),
};
}

/// Calls [confirm](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm)
/// function.
pub fn confirm(&mut self, message: &str) -> bool {
let value: Value = js! { return confirm(@{message}); };
match value {
Value::Bool(result) => result,
_ => false,
cfg_match! {
feature = "std_web" => ({
let value: Value = js! { return confirm(@{message}); };
match value {
Value::Bool(result) => result,
_ => false,
}
}),
feature = "web_sys" => utils::window().confirm_with_message(message).unwrap(),
}
}
}
14 changes: 7 additions & 7 deletions src/services/fetch.rs
Expand Up @@ -3,7 +3,6 @@
use super::Task;
use crate::callback::Callback;
use crate::format::{Binary, Format, Text};
use failure::Fail;
use serde::Serialize;
use std::collections::HashMap;
use std::fmt;
Expand All @@ -13,6 +12,7 @@ use stdweb::web::ArrayBuffer;
use stdweb::{JsSerialize, Value};
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
use thiserror::Error;

pub use http::{HeaderMap, Method, Request, Response, StatusCode, Uri};

Expand Down Expand Up @@ -90,9 +90,9 @@ pub struct FetchOptions {
}

/// Represents errors of a fetch service.
#[derive(Debug, Fail)]
#[derive(Debug, Error)]
enum FetchError {
#[fail(display = "failed response")]
#[error("failed response")]
FailedResponse,
}

Expand Down Expand Up @@ -157,10 +157,10 @@ impl FetchService {
///# fn dont_execute() {
///# let link: ComponentLink<Comp> = unimplemented!();
///# let mut fetch_service: FetchService = FetchService::new();
///# let post_request: Request<Result<String, failure::Error>> = unimplemented!();
///# let post_request: Request<Result<String, anyhow::Error>> = unimplemented!();
/// let task = fetch_service.fetch(
/// post_request,
/// link.callback(|response: Response<Result<String, failure::Error>>| {
/// link.callback(|response: Response<Result<String, anyhow::Error>>| {
/// if response.status().is_success() {
/// Msg::Noop
/// } else {
Expand Down Expand Up @@ -201,7 +201,7 @@ impl FetchService {
///# fn dont_execute() {
///# let link: ComponentLink<Comp> = unimplemented!();
/// let get_request = Request::get("/thing").body(Nothing).unwrap();
/// let callback = link.callback(|response: Response<Json<Result<Data, failure::Error>>>| {
/// let callback = link.callback(|response: Response<Json<Result<Data, anyhow::Error>>>| {
/// if let (meta, Json(Ok(body))) = response.into_parts() {
/// if meta.status.is_success() {
/// return Msg::FetchResourceComplete(body);
Expand Down Expand Up @@ -245,7 +245,7 @@ impl FetchService {
///# pub enum Msg {}
///# fn dont_execute() {
///# let link: ComponentLink<Comp> = unimplemented!();
///# let callback = link.callback(|response: Response<Result<String, failure::Error>>| unimplemented!());
///# let callback = link.callback(|response: Response<Result<String, anyhow::Error>>| unimplemented!());
/// let request = fetch::Request::get("/path/")
/// .body(Nothing)
/// .unwrap();
Expand Down
51 changes: 35 additions & 16 deletions src/services/interval.rs
Expand Up @@ -3,16 +3,27 @@

use super::{to_ms, Task};
use crate::callback::Callback;
use cfg_if::cfg_if;
daxpedda marked this conversation as resolved.
Show resolved Hide resolved
use cfg_match::cfg_match;
use std::fmt;
use std::time::Duration;
use stdweb::Value;
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::Value;
#[allow(unused_imports)]
use stdweb::{_js_impl, js};
} else if #[cfg(feature = "web_sys")] {
use gloo::timers::callback::Interval;
}
}

/// A handle which helps to cancel interval. Uses
/// [clearInterval](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval).
#[must_use]
pub struct IntervalTask(Option<Value>);
pub struct IntervalTask(
#[cfg(feature = "std_web")] Option<Value>,
#[cfg(feature = "web_sys")] Option<Interval>,
);

impl fmt::Debug for IntervalTask {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -37,16 +48,19 @@ impl IntervalService {
callback.emit(());
};
let ms = to_ms(duration);
let handle = js! {
var callback = @{callback};
var action = function() {
callback();
};
var delay = @{ms};
return {
interval_id: setInterval(action, delay),
callback: callback,
};
let handle = cfg_match! {
feature = "std_web" => js! {
var callback = @{callback};
var action = function() {
callback();
};
var delay = @{ms};
return {
interval_id: setInterval(action, delay),
callback: callback,
};
},
feature = "web_sys" => Interval::new(ms, callback),
};
IntervalTask(Some(handle))
}
Expand All @@ -57,7 +71,9 @@ impl Task for IntervalTask {
self.0.is_some()
}
fn cancel(&mut self) {
#[cfg_attr(feature = "web_sys", allow(unused_variables))]
let handle = self.0.take().expect("tried to cancel interval twice");
#[cfg(feature = "std_web")]
js! { @(no_return)
var handle = @{handle};
clearInterval(handle.interval_id);
Expand All @@ -68,8 +84,11 @@ impl Task for IntervalTask {

impl Drop for IntervalTask {
fn drop(&mut self) {
if self.is_active() {
self.cancel();
#[cfg(feature = "std_web")]
{
if self.is_active() {
self.cancel();
}
}
}
}