Skip to content

Commit

Permalink
Setting up WASM logging in diplomat-runtime (#346)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbastian authored Oct 19, 2023
1 parent 54e85c8 commit 2a52612
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 45 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions example/js/lib/api/diplomat-wasm.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions feature_tests/js/api/diplomat-wasm.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ repository = "https://github.com/rust-diplomat/diplomat"
path = "src/lib.rs"

[dependencies]
log = { version = "0.4", optional = true }
3 changes: 1 addition & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ extern crate alloc;
use alloc::alloc::Layout;

#[cfg(target_arch = "wasm32")]
// defines `extern "C" diplomat_init()`
mod wasm_glue;
#[cfg(target_arch = "wasm32")]
pub use wasm_glue::{console_log, console_trace, console_warn};

mod writeable;
pub use writeable::DiplomatWriteable;
Expand Down
119 changes: 85 additions & 34 deletions runtime/src/wasm_glue.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,94 @@
// minimal WASM logger based on https://github.com/DeMille/wasm-glue
extern "C" {
fn trace_js(ptr: *const u8, len: usize);
fn warn_js(ptr: *const u8, len: usize);
fn log_js(ptr: *const u8, len: usize);
use alloc::format;
use core::panic::PanicInfo;

#[no_mangle]
unsafe extern "C" fn diplomat_init() {
#[cfg(debug_assertions)]
std::panic::set_hook(Box::new(panic_handler));
#[cfg(feature = "log")]
log::set_logger(&ConsoleLogger)
.map(|()| log::set_max_level(log::LevelFilter::Debug))
.unwrap();
}

/// Throw an exception.
pub fn console_trace(msg: &str) {
unsafe {
trace_js(msg.as_ptr(), msg.len());
fn panic_handler(info: &PanicInfo) {
let msg = match info.payload().downcast_ref::<&'static str>() {
Some(&s) => s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => s.as_str(),
None => "Box<Any>",
},
};

let msg = match info.location() {
Some(l) => format!(
"wasm panicked at {}:{}:{}:\n{msg}",
l.file(),
l.line(),
l.column(),
),
None => format!("wasm panicked at <unknown location>:\n{msg}"),
};

extern "C" {
fn diplomat_throw_error_js(ptr: *const u8, len: usize);
}
}

/// Write a message to `console.warn`.
pub fn console_warn(msg: &str) {
unsafe { warn_js(msg.as_ptr(), msg.len()) }
unsafe { diplomat_throw_error_js(msg.as_ptr(), msg.len()) }
}

/// Write a message to `console.log`.
pub fn console_log(msg: &str) {
unsafe { log_js(msg.as_ptr(), msg.len()) }
}
#[cfg(feature = "log")]
struct ConsoleLogger;

#[no_mangle]
pub unsafe extern "C" fn diplomat_init() {
#[cfg(debug_assertions)]
// Sets a custom panic hook using `trace_js`, which by default crates a JS error
std::panic::set_hook(Box::new(|info| {
let file = info.location().unwrap().file();
let line = info.location().unwrap().line();
let col = info.location().unwrap().column();

let msg = match info.payload().downcast_ref::<&'static str>() {
Some(&s) => s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => s.as_str(),
None => "Box<Any>",
},
#[cfg(feature = "log")]
impl log::Log for ConsoleLogger {
#[inline]
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= log::max_level()
}

fn log(&self, record: &log::Record) {
if !self.enabled(record.metadata()) {
return;
}

let out = match record.level() {
log::Level::Error => {
extern "C" {
fn diplomat_console_error_js(ptr: *const u8, len: usize);
}
diplomat_console_error_js
}
log::Level::Warn => {
extern "C" {
fn diplomat_console_warn_js(ptr: *const u8, len: usize);
}
diplomat_console_warn_js
}
log::Level::Info => {
extern "C" {
fn diplomat_console_info_js(ptr: *const u8, len: usize);
}
diplomat_console_info_js
}
log::Level::Debug => {
extern "C" {
fn diplomat_console_log_js(ptr: *const u8, len: usize);
}
diplomat_console_log_js
}
log::Level::Trace => {
extern "C" {
fn diplomat_console_debug_js(ptr: *const u8, len: usize);
}
diplomat_console_debug_js
}
};
console_trace(&format!("Panicked at '{msg}', {file}:{line}:{col}"));
}));

let msg = alloc::format!("{}", record.args());

unsafe { out(msg.as_ptr(), msg.len()) };
}

fn flush(&self) {}
}
15 changes: 12 additions & 3 deletions tool/src/js/wasm.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@ let wasm;

const imports = {
env: {
log_js(ptr, len) {
diplomat_console_debug_js(ptr, len) {
console.debug(readString(wasm, ptr, len));
},
diplomat_console_error_js(ptr, len) {
console.error(readString(wasm, ptr, len));
},
diplomat_console_info_js(ptr, len) {
console.info(readString(wasm, ptr, len));
},
diplomat_console_log_js(ptr, len) {
console.log(readString(wasm, ptr, len));
},
warn_js(ptr, len) {
diplomat_console_warn_js(ptr, len) {
console.warn(readString(wasm, ptr, len));
},
trace_js(ptr, len) {
diplomat_throw_error_js(ptr, len) {
throw new Error(readString(wasm, ptr, len));
}
}
Expand Down

0 comments on commit 2a52612

Please sign in to comment.