Skip to content

Commit c01ca76

Browse files
committed
lsp: Make WASM build again
... the wasm preview still does not work though.
1 parent 3c7694d commit c01ca76

File tree

8 files changed

+94
-63
lines changed

8 files changed

+94
-63
lines changed

internal/compiler/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ pub type FontCache = Rc<
9191
>,
9292
>;
9393

94+
pub type OpenImportFallback =
95+
Rc<dyn Fn(String) -> Pin<Box<dyn Future<Output = Option<std::io::Result<String>>>>>>;
96+
pub type ResourceUrlMapper = Rc<dyn Fn(&str) -> Pin<Box<dyn Future<Output = Option<String>>>>>;
97+
9498
/// CompilationConfiguration allows configuring different aspects of the compiler.
9599
#[derive(Clone)]
96100
pub struct CompilerConfiguration {
@@ -111,14 +115,11 @@ pub struct CompilerConfiguration {
111115
///
112116
/// The callback should open the file specified by the given file name and
113117
/// return an future that provides the text content of the file as output.
114-
pub open_import_fallback: Option<
115-
Rc<dyn Fn(String) -> Pin<Box<dyn Future<Output = Option<std::io::Result<String>>>>>>,
116-
>,
118+
pub open_import_fallback: Option<OpenImportFallback>,
117119
/// Callback to map URLs for resources
118120
///
119121
/// The function takes the url and returns the mapped URL (or None if not mapped)
120-
pub resource_url_mapper:
121-
Option<Rc<dyn Fn(&str) -> Pin<Box<dyn Future<Output = Option<String>>>>>>,
122+
pub resource_url_mapper: Option<ResourceUrlMapper>,
122123

123124
/// Run the pass that inlines all the elements.
124125
///

tools/lsp/common/document_cache.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,19 @@ fn default_cc() -> i_slint_compiler::CompilerConfiguration {
3232
)
3333
}
3434

35-
pub type OpenImportFallback = Option<
36-
Rc<
37-
dyn Fn(
38-
String,
39-
) -> Pin<
40-
Box<dyn Future<Output = Option<std::io::Result<(SourceFileVersion, String)>>>>,
41-
>,
42-
>,
35+
/// This is i_slint_compiler::OpenImportFallback with version information
36+
pub type OpenImportFallback = Rc<
37+
dyn Fn(
38+
String,
39+
)
40+
-> Pin<Box<dyn Future<Output = Option<std::io::Result<(SourceFileVersion, String)>>>>>,
4341
>;
4442

4543
pub struct CompilerConfiguration {
4644
pub include_paths: Vec<std::path::PathBuf>,
4745
pub library_paths: HashMap<String, std::path::PathBuf>,
4846
pub style: Option<String>,
49-
pub open_import_fallback: OpenImportFallback,
47+
pub open_import_fallback: Option<OpenImportFallback>,
5048
pub resource_url_mapper:
5149
Option<Rc<dyn Fn(&str) -> Pin<Box<dyn Future<Output = Option<String>>>>>>,
5250
}
@@ -66,7 +64,7 @@ impl Default for CompilerConfiguration {
6664
}
6765

6866
impl CompilerConfiguration {
69-
fn build(mut self) -> (i_slint_compiler::CompilerConfiguration, OpenImportFallback) {
67+
fn build(mut self) -> (i_slint_compiler::CompilerConfiguration, Option<OpenImportFallback>) {
7068
let mut result = default_cc();
7169
result.include_paths = std::mem::take(&mut self.include_paths);
7270
result.library_paths = std::mem::take(&mut self.library_paths);
@@ -80,16 +78,16 @@ impl CompilerConfiguration {
8078
/// A cache of loaded documents
8179
pub struct DocumentCache {
8280
type_loader: TypeLoader,
83-
open_import_fallback: OpenImportFallback,
81+
open_import_fallback: Option<OpenImportFallback>,
8482
source_file_versions: Rc<RefCell<SourceFileVersionMap>>,
8583
}
8684

8785
#[cfg(feature = "preview-engine")]
8886
pub fn document_cache_parts_setup(
8987
compiler_config: &mut i_slint_compiler::CompilerConfiguration,
90-
open_import_fallback: OpenImportFallback,
88+
open_import_fallback: Option<OpenImportFallback>,
9189
initial_file_versions: SourceFileVersionMap,
92-
) -> (OpenImportFallback, Rc<RefCell<SourceFileVersionMap>>) {
90+
) -> (Option<OpenImportFallback>, Rc<RefCell<SourceFileVersionMap>>) {
9391
let source_file_versions = Rc::new(RefCell::new(initial_file_versions));
9492
DocumentCache::wire_up_import_fallback(
9593
compiler_config,
@@ -101,9 +99,9 @@ pub fn document_cache_parts_setup(
10199
impl DocumentCache {
102100
fn wire_up_import_fallback(
103101
compiler_config: &mut i_slint_compiler::CompilerConfiguration,
104-
open_import_fallback: OpenImportFallback,
102+
open_import_fallback: Option<OpenImportFallback>,
105103
source_file_versions: Rc<RefCell<SourceFileVersionMap>>,
106-
) -> (OpenImportFallback, Rc<RefCell<SourceFileVersionMap>>) {
104+
) -> (Option<OpenImportFallback>, Rc<RefCell<SourceFileVersionMap>>) {
107105
let sfv = source_file_versions.clone();
108106
if let Some(open_import_fallback) = open_import_fallback.clone() {
109107
compiler_config.open_import_fallback = Some(Rc::new(move |file_name: String| {
@@ -152,7 +150,7 @@ impl DocumentCache {
152150

153151
pub fn new_from_raw_parts(
154152
mut type_loader: TypeLoader,
155-
open_import_fallback: OpenImportFallback,
153+
open_import_fallback: Option<OpenImportFallback>,
156154
source_file_versions: Rc<RefCell<SourceFileVersionMap>>,
157155
) -> Self {
158156
let (open_import_fallback, source_file_versions) = Self::wire_up_import_fallback(

tools/lsp/common/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async fn parse_source(
4040
}));
4141
#[cfg(target_arch = "wasm32")]
4242
{
43-
tmp.resource_url_mapper = resource_url_mapper();
43+
tmp.resource_url_mapper = crate::preview::connector::resource_url_mapper();
4444
}
4545
tmp
4646
};

tools/lsp/preview.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
1111
use crate::common::{
1212
self, component_catalog, rename_component, ComponentInformation, ElementRcNode,
13-
PreviewComponent, PreviewConfig, PreviewToLsp, PreviewToLspMessage, SourceFileVersion,
13+
PreviewComponent, PreviewConfig, PreviewToLspMessage, SourceFileVersion,
1414
};
1515
use crate::preview::element_selection::ElementSelection;
1616
use crate::util;
@@ -51,7 +51,7 @@ pub fn run(config: &crate::LivePreview) -> std::result::Result<(), slint::Platfo
5151
));
5252
}
5353

54-
let to_lsp: Rc<dyn PreviewToLsp> = Rc::new(connector::NativePreviewToLsp::new());
54+
let to_lsp: Rc<dyn common::PreviewToLsp> = Rc::new(connector::NativePreviewToLsp::new());
5555

5656
let experimental = std::env::var_os("SLINT_ENABLE_EXPERIMENTAL_FEATURES").is_some();
5757
let ui = ui::create_ui(&to_lsp, &config.style, experimental)?;
@@ -1316,7 +1316,7 @@ async fn parse_source(
13161316
) -> (
13171317
Vec<diagnostics::Diagnostic>,
13181318
Option<ComponentDefinition>,
1319-
common::document_cache::OpenImportFallback,
1319+
Option<common::document_cache::OpenImportFallback>,
13201320
Rc<RefCell<common::document_cache::SourceFileVersionMap>>,
13211321
) {
13221322
let mut builder = slint_interpreter::Compiler::default();
@@ -1327,10 +1327,7 @@ async fn parse_source(
13271327
} else {
13281328
i_slint_compiler::ComponentSelection::LastExported
13291329
};
1330-
#[cfg(target_arch = "wasm32")]
1331-
{
1332-
cc.resource_url_mapper = connector::resource_url_mapper();
1333-
}
1330+
cc.resource_url_mapper = connector::resource_url_mapper();
13341331
cc.embed_resources = EmbedResourcesKind::ListAllResources;
13351332
cc.no_native_menu = true;
13361333
// Otherwise this may cause a runtime panic because of the recursion
@@ -1825,7 +1822,7 @@ fn set_status_text(text: &str) {
18251822
fn update_preview_area(
18261823
compiled: Option<ComponentDefinition>,
18271824
behavior: LoadBehavior,
1828-
open_import_fallback: common::document_cache::OpenImportFallback,
1825+
open_import_fallback: Option<common::document_cache::OpenImportFallback>,
18291826
source_file_versions: Rc<RefCell<common::document_cache::SourceFileVersionMap>>,
18301827
) -> Result<(), PlatformError> {
18311828
PREVIEW_STATE.with_borrow_mut(move |preview_state| {

tools/lsp/preview/connector.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33

44
#[cfg(all(target_arch = "wasm32", feature = "preview-external"))]
55
mod wasm;
6-
7-
#[cfg(target_arch = "wasm32")]
8-
use crate::wasm_prelude::*;
96
#[cfg(all(target_arch = "wasm32", feature = "preview-external"))]
107
pub use wasm::*;
8+
119
#[cfg(all(not(target_arch = "wasm32"), feature = "preview-builtin"))]
1210
mod native;
1311
#[cfg(all(not(target_arch = "wasm32"), feature = "preview-builtin"))]

tools/lsp/preview/connector/native.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use crate::{common, preview};
88
use std::cell::RefCell;
99
use std::io::{BufRead as _, Write as _};
1010

11+
pub fn resource_url_mapper() -> Option<i_slint_compiler::ResourceUrlMapper> {
12+
None
13+
}
14+
1115
struct NativeLspToPreviewInner {
1216
communication_handle: std::thread::JoinHandle<std::result::Result<(), String>>,
1317
to_child: std::process::ChildStdin,

tools/lsp/preview/connector/wasm.rs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
#![cfg(target_arch = "wasm32")]
66

77
use crate::common;
8-
use crate::preview::{self, ui};
8+
use crate::preview::{self, connector, ui};
99

1010
use slint_interpreter::ComponentHandle;
1111

1212
use std::cell::RefCell;
13-
use std::future::Future;
14-
use std::pin::Pin;
1513
use std::rc::Rc;
1614

1715
use wasm_bindgen::prelude::*;
@@ -33,11 +31,14 @@ extern "C" {
3331
pub type PreviewConnectorPromise;
3432
}
3533

34+
// We have conceptually two threads: The UI thread and the JS runtime, even though
35+
// the WASM is strictly single threaded.
36+
//
37+
// So we use a thread local variable to transfer data between the two conceptual threads.
3638
struct WasmCallbacks {
3739
lsp_notifier: SignalLspFunction,
3840
resource_url_mapper: ResourceUrlMapperFunction,
3941
}
40-
4142
thread_local! {static WASM_CALLBACKS: RefCell<Option<WasmCallbacks>> = Default::default();}
4243

4344
#[wasm_bindgen(start)]
@@ -83,14 +84,18 @@ impl PreviewConnector {
8384
let reject_c = send_wrapper::SendWrapper::new(reject.clone());
8485
let style = style.clone();
8586
if let Err(e) = slint_interpreter::invoke_from_event_loop(move || {
87+
let to_lsp: Rc<dyn common::PreviewToLsp> = Rc::new(WasmPreviewToLsp::default());
88+
8689
preview::PREVIEW_STATE.with(move |preview_state| {
8790
if preview_state.borrow().ui.is_some() {
8891
reject_c.take().call1(&JsValue::UNDEFINED,
8992
&JsValue::from("PreviewConnector already set up.")).unwrap_throw();
9093
} else {
91-
match ui::create_ui(style, experimental) {
94+
match ui::create_ui(&to_lsp, &style, experimental) {
9295
Ok(ui) => {
9396
preview_state.borrow_mut().ui = Some(ui);
97+
*preview_state.borrow().to_lsp.borrow_mut() = Some(to_lsp);
98+
9499
resolve.take().call1(&JsValue::UNDEFINED,
95100
&JsValue::from(Self { })).unwrap_throw()
96101
}
@@ -127,7 +132,7 @@ impl PreviewConnector {
127132
let message = serde_wasm_bindgen::from_value(value)
128133
.map_err(|e| -> JsValue { format!("{e:?}").into() })?;
129134
i_slint_core::api::invoke_from_event_loop(move || {
130-
lsp_to_preview_message(message);
135+
connector::lsp_to_preview(message);
131136
})
132137
.map_err(|e| -> JsValue { format!("{e:?}").into() })?;
133138
Ok(())
@@ -190,8 +195,7 @@ fn invoke_from_event_loop_wrapped_in_promise(
190195
}))
191196
}
192197

193-
pub fn resource_url_mapper(
194-
) -> Option<Rc<dyn Fn(&str) -> Pin<Box<dyn Future<Output = Option<String>>>>>> {
198+
pub fn resource_url_mapper() -> Option<i_slint_compiler::ResourceUrlMapper> {
195199
let callback = WASM_CALLBACKS.with_borrow(|callbacks| {
196200
callbacks.as_ref().map(|cb| js_sys::Function::from((cb.resource_url_mapper).clone()))
197201
})?;
@@ -205,16 +209,36 @@ pub fn resource_url_mapper(
205209
}))
206210
}
207211

208-
pub fn send_message_to_lsp(message: common::PreviewToLspMessage) {
209-
WASM_CALLBACKS.with_borrow(|callbacks| {
210-
if let Some(callbacks) = &callbacks {
211-
let notifier = js_sys::Function::from((callbacks.lsp_notifier).clone());
212-
let value = serde_wasm_bindgen::to_value(&message).unwrap();
213-
let _ = notifier.call1(&JsValue::UNDEFINED, &value);
214-
}
215-
})
212+
pub struct WasmLspToPreview {
213+
server_notifier: crate::ServerNotifier,
216214
}
217215

218-
fn lsp_to_preview_message(message: common::LspToPreviewMessage) {
219-
super::lsp_to_preview_message_impl(message);
216+
impl WasmLspToPreview {
217+
pub fn new(server_notifier: crate::ServerNotifier) -> Self {
218+
Self { server_notifier }
219+
}
220+
}
221+
222+
impl common::LspToPreview for WasmLspToPreview {
223+
fn send(&self, message: &common::LspToPreviewMessage) -> common::Result<()> {
224+
self.server_notifier.send_notification::<common::LspToPreviewMessage>(message.clone())
225+
}
226+
}
227+
228+
#[derive(Default)]
229+
struct WasmPreviewToLsp {}
230+
231+
impl common::PreviewToLsp for WasmPreviewToLsp {
232+
fn send(&self, message: &common::PreviewToLspMessage) -> common::Result<()> {
233+
WASM_CALLBACKS.with_borrow(|callbacks| {
234+
let notifier = js_sys::Function::from(
235+
(callbacks.as_ref().expect("Callbacks were set up earlier").lsp_notifier).clone(),
236+
);
237+
let value = serde_wasm_bindgen::to_value(&message)?;
238+
notifier
239+
.call1(&JsValue::UNDEFINED, &value)
240+
.map_err(|_| "Failed to send message to LSP".to_string())?;
241+
Ok(())
242+
})
243+
}
220244
}

tools/lsp/wasm_main.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod language;
1111
mod preview;
1212
pub mod util;
1313

14-
use common::{DocumentCache, LspToPreviewMessage, Result, VersionedUrl};
14+
use common::{DocumentCache, LspToPreview, LspToPreviewMessage, Result, VersionedUrl};
1515
use js_sys::Function;
1616
pub use language::{Context, RequestHandler};
1717
use lsp_types::Url;
@@ -77,9 +77,9 @@ impl ServerNotifier {
7777
})
7878
}
7979

80-
pub fn send_message_to_preview(&self, message: LspToPreviewMessage) {
81-
let _ = self.send_notification::<LspToPreviewMessage>(message);
82-
}
80+
// pub fn send_message_to_preview(&self, message: LspToPreviewMessage) {
81+
// let _ = self.send_notification::<LspToPreviewMessage>(message);
82+
// }
8383
}
8484

8585
impl RequestHandler {
@@ -190,20 +190,28 @@ pub fn create(
190190

191191
let mut compiler_config = crate::common::document_cache::CompilerConfiguration::default();
192192

193-
let server_notifier_ = server_notifier.clone();
193+
#[cfg(not(feature = "preview-engine"))]
194+
let to_preview: Rc<dyn LspToPreview> = Rc::new(common::DummyLspToPreview::default());
195+
#[cfg(feature = "preview-engine")]
196+
let to_preview: Rc<dyn LspToPreview> =
197+
Rc::new(preview::connector::WasmLspToPreview::new(server_notifier.clone()));
198+
199+
let to_preview_clone = to_preview.clone();
194200
compiler_config.open_import_fallback = Some(Rc::new(move |path| {
195201
let load_file = Function::from(load_file.clone());
196-
let server_notifier = server_notifier_.clone();
202+
let to_preview = to_preview_clone.clone();
197203
Box::pin(async move {
198204
let contents = self::load_file(path.clone(), &load_file).await;
199205
let Ok(url) = Url::from_file_path(&path) else {
200206
return Some(contents.map(|c| (None, c)));
201207
};
202208
if let Ok(contents) = &contents {
203-
server_notifier.send_message_to_preview(LspToPreviewMessage::SetContents {
204-
url: VersionedUrl::new(url, None),
205-
contents: contents.clone(),
206-
})
209+
to_preview
210+
.send(&LspToPreviewMessage::SetContents {
211+
url: VersionedUrl::new(url, None),
212+
contents: contents.clone(),
213+
})
214+
.unwrap()
207215
}
208216
Some(contents.map(|c| (None, c)))
209217
})
@@ -222,13 +230,14 @@ pub fn create(
222230
server_notifier,
223231
to_show: Default::default(),
224232
open_urls: Default::default(),
233+
to_preview,
225234
}),
226235
reentry_guard,
227236
rh: Rc::new(rh),
228237
})
229238
}
230239

231-
fn send_workspace_edit(
240+
fn forward_workspace_edit(
232241
server_notifier: ServerNotifier,
233242
label: Option<String>,
234243
edit: Result<lsp_types::WorkspaceEdit>,
@@ -294,7 +303,7 @@ impl SlintServer {
294303
crate::language::request_state(&self.ctx);
295304
}
296305
M::SendWorkspaceEdit { label, edit } => {
297-
send_workspace_edit(self.ctx.server_notifier.clone(), label, Ok(edit));
306+
forward_workspace_edit(self.ctx.server_notifier.clone(), label, Ok(edit));
298307
}
299308
M::SendShowMessage { message } => {
300309
let _ = self

0 commit comments

Comments
 (0)