Assert that launch never returns for better compiler errors (#2517)
* assert that launch never returns for better compiler errors * fix static generation launch function * fix web renderer
This commit is contained in:
1 parent
5e3bb4f549
commit
f4a62fad6b
5 files changed
+104
-49
No files matched your search
@@ -11,7 +11,7 @@ use tao::event::{Event, StartCause, WindowEvent};
|
||||
///
|
||||
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
||||
/// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
||||
pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, desktop_config: Config) {
|
||||
pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
|
||||
let (event_loop, mut app) = App::new(desktop_config, virtual_dom);
|
||||
|
||||
event_loop.run(move |window_event, _, control_flow| {
|
||||
@@ -66,7 +66,7 @@ pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, desktop_config: Conf
|
||||
}
|
||||
|
||||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) {
|
||||
pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
|
||||
#[cfg(feature = "tokio")]
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
@@ -77,7 +77,9 @@ pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) {
|
||||
}));
|
||||
|
||||
#[cfg(not(feature = "tokio"))]
|
||||
launch_virtual_dom_blocking(virtual_dom, desktop_config)
|
||||
launch_virtual_dom_blocking(virtual_dom, desktop_config);
|
||||
|
||||
unreachable!("The desktop launch function will never exit")
|
||||
}
|
||||
|
||||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
@@ -85,7 +87,7 @@ pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any>>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
) -> ! {
|
||||
let mut virtual_dom = VirtualDom::new(root);
|
||||
|
||||
for context in contexts {
|
||||
|
||||
@@ -55,7 +55,7 @@ impl LaunchBuilder {
|
||||
)]
|
||||
pub fn new() -> LaunchBuilder<current_platform::Config, ValidContext> {
|
||||
LaunchBuilder {
|
||||
launch_fn: current_platform::launch,
|
||||
launch_fn: |root, contexts, cfg| current_platform::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
}
|
||||
@@ -77,7 +77,7 @@ impl LaunchBuilder {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))]
|
||||
pub fn desktop() -> LaunchBuilder<dioxus_desktop::Config, UnsendContext> {
|
||||
LaunchBuilder {
|
||||
launch_fn: dioxus_desktop::launch::launch,
|
||||
launch_fn: |root, contexts, cfg| dioxus_desktop::launch::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
}
|
||||
@@ -88,7 +88,7 @@ impl LaunchBuilder {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "fullstack")))]
|
||||
pub fn fullstack() -> LaunchBuilder<dioxus_fullstack::Config, SendContext> {
|
||||
LaunchBuilder {
|
||||
launch_fn: dioxus_fullstack::launch::launch,
|
||||
launch_fn: |root, contexts, cfg| dioxus_fullstack::launch::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
}
|
||||
@@ -99,7 +99,7 @@ impl LaunchBuilder {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
||||
pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config, UnsendContext> {
|
||||
LaunchBuilder {
|
||||
launch_fn: dioxus_mobile::launch::launch,
|
||||
launch_fn: |root, contexts, cfg| dioxus_mobile::launch::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
}
|
||||
@@ -188,12 +188,23 @@ impl<Cfg: Default + 'static, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
|
||||
self
|
||||
}
|
||||
|
||||
// Static generation is the only platform that may exit. We can't use the `!` type here
|
||||
#[cfg(any(feature = "static-generation", feature = "web"))]
|
||||
/// Launch your application.
|
||||
pub fn launch(self, app: fn() -> Element) {
|
||||
let cfg = self.platform_config.unwrap_or_default();
|
||||
|
||||
(self.launch_fn)(app, self.contexts, cfg)
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "static-generation", feature = "web")))]
|
||||
/// Launch your application.
|
||||
pub fn launch(self, app: fn() -> Element) -> ! {
|
||||
let cfg = self.platform_config.unwrap_or_default();
|
||||
|
||||
(self.launch_fn)(app, self.contexts, cfg);
|
||||
unreachable!("Launching an application will never exit")
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-export the platform we expect the user wants
|
||||
@@ -308,17 +319,20 @@ mod current_platform {
|
||||
root: fn() -> dioxus_core::Element,
|
||||
contexts: Vec<Box<super::ValidContext>>,
|
||||
platform_config: (),
|
||||
) {
|
||||
) -> ! {
|
||||
#[cfg(feature = "third-party-renderer")]
|
||||
panic!("No first party renderer feature enabled. It looks like you are trying to use a third party renderer. You will need to use the launch function from the third party renderer crate.");
|
||||
|
||||
panic!("No platform feature enabled. Please enable one of the following features: liveview, desktop, mobile, web, tui, fullstack to use the launch API.");
|
||||
panic!("No platform feature enabled. Please enable one of the following features: liveview, desktop, mobile, web, tui, fullstack to use the launch API.")
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
// If you aren't using a third party renderer and this is not a docs.rs build, generate a warning about no renderer being enabled
|
||||
#[cfg_attr(
|
||||
// ! is unstable, so we can't name the type with an alias. Instead we need to generate different variants of items with macros
|
||||
macro_rules! impl_launch {
|
||||
($($return_type:tt),*) => {
|
||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
// If you aren't using a third party renderer and this is not a docs.rs build, generate a warning about no renderer being enabled
|
||||
#[cfg_attr(
|
||||
all(not(any(
|
||||
docsrs,
|
||||
feature = "third-party-renderer",
|
||||
@@ -332,12 +346,20 @@ mod current_platform {
|
||||
deprecated(
|
||||
note = "No renderer is enabled. You must enable a renderer feature on the dioxus crate before calling the launch function.\nAdd `web`, `desktop`, `mobile`, `fullstack`, or `static-generation` to the `features` of dioxus field in your Cargo.toml.\n# Example\n```toml\n# ...\n[dependencies]\ndioxus = { version = \"0.5.0\", features = [\"web\"] }\n# ...\n```"
|
||||
)
|
||||
)]
|
||||
pub fn launch(app: fn() -> Element) {
|
||||
)]
|
||||
pub fn launch(app: fn() -> Element) -> $($return_type)* {
|
||||
#[allow(deprecated)]
|
||||
LaunchBuilder::new().launch(app)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Static generation is the only platform that may exit. We can't use the `!` type here
|
||||
#[cfg(any(feature = "static-generation", feature = "web"))]
|
||||
impl_launch!(());
|
||||
#[cfg(not(any(feature = "static-generation", feature = "web")))]
|
||||
impl_launch!(!);
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
|
||||
/// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
|
||||
@@ -6,6 +6,39 @@ use dioxus_lib::prelude::{Element, VirtualDom};
|
||||
|
||||
pub use crate::Config;
|
||||
|
||||
fn virtual_dom_factory(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
) -> impl Fn() -> VirtualDom + 'static {
|
||||
move || {
|
||||
let mut vdom = VirtualDom::new(root);
|
||||
for context in &contexts {
|
||||
vdom.insert_any_root_context(context());
|
||||
}
|
||||
vdom
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
/// Launch a fullstack app with the given root component, contexts, and config.
|
||||
#[allow(unused)]
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Config,
|
||||
) -> ! {
|
||||
let factory = virtual_dom_factory(root, contexts);
|
||||
#[cfg(all(feature = "server", not(target_arch = "wasm32")))]
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async move {
|
||||
platform_config.launch_server(factory).await;
|
||||
});
|
||||
|
||||
unreachable!("Launching a fullstack app should never return")
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "server"), feature = "web"))]
|
||||
/// Launch a fullstack app with the given root component, contexts, and config.
|
||||
#[allow(unused)]
|
||||
pub fn launch(
|
||||
@@ -13,40 +46,36 @@ pub fn launch(
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
let virtual_dom_factory = move || {
|
||||
let mut vdom = VirtualDom::new(root);
|
||||
for context in &contexts {
|
||||
vdom.insert_any_root_context(context());
|
||||
}
|
||||
vdom
|
||||
};
|
||||
|
||||
#[cfg(all(feature = "server", not(target_arch = "wasm32")))]
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async move {
|
||||
platform_config.launch_server(virtual_dom_factory).await;
|
||||
});
|
||||
|
||||
#[cfg(not(feature = "server"))]
|
||||
{
|
||||
#[cfg(feature = "web")]
|
||||
{
|
||||
// TODO: this should pull the props from the document
|
||||
let factory = virtual_dom_factory(root, contexts);
|
||||
let cfg = platform_config.web_cfg.hydrate(true);
|
||||
dioxus_web::launch::launch_virtual_dom(virtual_dom_factory(), cfg);
|
||||
}
|
||||
dioxus_web::launch::launch_virtual_dom(factory(), cfg)
|
||||
}
|
||||
|
||||
#[cfg(feature = "desktop")]
|
||||
{
|
||||
#[cfg(all(not(any(feature = "server", feature = "web")), feature = "desktop"))]
|
||||
/// Launch a fullstack app with the given root component, contexts, and config.
|
||||
#[allow(unused)]
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Config,
|
||||
) -> ! {
|
||||
let factory = virtual_dom_factory(root, contexts);
|
||||
let cfg = platform_config.desktop_cfg;
|
||||
dioxus_desktop::launch::launch_virtual_dom(virtual_dom_factory(), cfg)
|
||||
}
|
||||
dioxus_desktop::launch::launch_virtual_dom(factory(), cfg)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mobile")]
|
||||
{
|
||||
#[cfg(all(
|
||||
not(any(feature = "server", feature = "web", feature = "desktop")),
|
||||
feature = "mobile"
|
||||
))]
|
||||
/// Launch a fullstack app with the given root component, contexts, and config.
|
||||
#[allow(unused)]
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
let factory = virtual_dom_factory(root, contexts);
|
||||
let cfg = platform_config.mobile_cfg;
|
||||
dioxus_mobile::launch::launch_virtual_dom(virtual_dom_factory(), cfg)
|
||||
}
|
||||
}
|
||||
dioxus_mobile::launch::launch_virtual_dom(factory(), cfg)
|
||||
}
|
||||
@@ -8,7 +8,7 @@ pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
) -> ! {
|
||||
#[cfg(feature = "multi-threaded")]
|
||||
let mut builder = tokio::runtime::Builder::new_multi_thread();
|
||||
#[cfg(not(feature = "multi-threaded"))]
|
||||
@@ -28,4 +28,6 @@ pub fn launch(
|
||||
.launch()
|
||||
.await;
|
||||
});
|
||||
|
||||
panic!("Launching a liveview app should never return")
|
||||
}
|
||||
@@ -16,7 +16,7 @@ pub fn launch(
|
||||
for context in contexts {
|
||||
vdom.insert_any_root_context(context());
|
||||
}
|
||||
launch_virtual_dom(vdom, platform_config);
|
||||
launch_virtual_dom(vdom, platform_config)
|
||||
}
|
||||
|
||||
/// Launch the web application with a prebuild virtual dom
|
||||
@@ -30,5 +30,5 @@ pub fn launch_virtual_dom(vdom: VirtualDom, platform_config: Config) {
|
||||
|
||||
/// Launch the web application with the given root component and config
|
||||
pub fn launch_cfg(root: fn() -> Element, platform_config: Config) {
|
||||
launch_virtual_dom(VirtualDom::new(root), platform_config);
|
||||
launch_virtual_dom(VirtualDom::new(root), platform_config)
|
||||
}
|
||||
Reference in new issue
Block a user