Skip to content

Commit

Permalink
Merge pull request #88 from Shopify/console-log-to-stder
Browse files Browse the repository at this point in the history
Send console.log and console.error to stderr
  • Loading branch information
jianghong authored Mar 7, 2022
2 parents c09667a + cbe8926 commit e7712e9
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 19 deletions.
38 changes: 26 additions & 12 deletions crates/cli/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fn test_identity() {
let _guard = EXCLUSIVE_TEST.lock();
let mut runner = Runner::default();

let output = run::<_, u32>(&mut runner, &42);
let (output, _) = run::<_, u32>(&mut runner, &42);
assert_eq!(42, output);
}

Expand All @@ -26,7 +26,7 @@ fn test_fib() {
let _guard = EXCLUSIVE_TEST.lock();
let mut runner = Runner::new("fib.js");

let output = run::<_, u32>(&mut runner, &5);
let (output, _) = run::<_, u32>(&mut runner, &5);
assert_eq!(8, output);
}

Expand All @@ -35,7 +35,7 @@ fn test_recursive_fib() {
let _guard = EXCLUSIVE_TEST.lock();
let mut runner = Runner::new("recursive-fib.js");

let output = run::<_, u32>(&mut runner, &5);
let (output, _) = run::<_, u32>(&mut runner, &5);
assert_eq!(8, output);
}

Expand All @@ -44,7 +44,7 @@ fn test_str() {
let _guard = EXCLUSIVE_TEST.lock();
let mut runner = Runner::new("str.js");

let output = run::<_, String>(&mut runner, &"hello".to_string());
let (output, _) = run::<_, String>(&mut runner, &"hello".to_string());
assert_eq!("world", output.as_str());
}

Expand All @@ -53,29 +53,43 @@ fn test_big_ints() {
let _guard = EXCLUSIVE_TEST.lock();
let mut runner = Runner::new("big-ints.js");

let output = run::<_, String>(&mut runner, &42);
let (output, _) = run::<_, String>(&mut runner, &42);
assert_eq!("a", output.as_str());

let output = run::<_, String>(&mut runner, &i64::MAX);
let (output, _) = run::<_, String>(&mut runner, &i64::MAX);
assert_eq!("b", output.as_str());

let output = run::<_, String>(&mut runner, &i64::MIN);
let (output, _) = run::<_, String>(&mut runner, &i64::MIN);
assert_eq!("c", output.as_str());

let output = run::<_, String>(&mut runner, &u64::MAX);
let (output, _) = run::<_, String>(&mut runner, &u64::MAX);
assert_eq!("d", output.as_str());

let output = run::<_, String>(&mut runner, &u64::MIN);
let (output, _) = run::<_, String>(&mut runner, &u64::MIN);
assert_eq!("e", output.as_str());
}

fn run<I, O>(r: &mut Runner, i: &I) -> O
#[test]
fn test_logging() {
let _guard = EXCLUSIVE_TEST.lock();
let mut runner = Runner::new("logging.js");

let (output, logs) = run::<_, u32>(&mut runner, &42);
assert_eq!(42, output);
assert_eq!(
"hello world from console.log\nhello world from console.error\n",
logs.as_str(),
);
}

fn run<I, O>(r: &mut Runner, i: &I) -> (O, String)
where
I: Serialize,
O: DeserializeOwned,
{
let input = rmp_serde::to_vec(i).unwrap();
let output = r.exec(input).unwrap();
let (output, logs) = r.exec(input).unwrap();
let output = rmp_serde::from_slice::<O>(&output).unwrap();
output
let logs = String::from_utf8(logs).unwrap();
(output, logs)
}
24 changes: 20 additions & 4 deletions crates/cli/tests/runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,36 @@ pub struct Runner {
struct StoreContext {
wasi_output: WritePipe<Cursor<Vec<u8>>>,
wasi: WasiCtx,
log_stream: WritePipe<Cursor<Vec<u8>>>,
}

impl Default for StoreContext {
fn default() -> Self {
let wasi_output = WritePipe::new_in_memory();
let log_stream = WritePipe::new_in_memory();
let mut wasi = WasiCtxBuilder::new().inherit_stdio().build();
wasi.set_stdout(Box::new(wasi_output.clone()));
Self { wasi, wasi_output }
wasi.set_stderr(Box::new(log_stream.clone()));
Self {
wasi,
wasi_output,
log_stream,
}
}
}

impl StoreContext {
fn new(input: Vec<u8>) -> Self {
let mut wasi = WasiCtxBuilder::new().inherit_stdio().build();
let wasi_output = WritePipe::new_in_memory();
let log_stream = WritePipe::new_in_memory();
wasi.set_stdout(Box::new(wasi_output.clone()));
wasi.set_stdin(Box::new(ReadPipe::from(input.clone())));
wasi.set_stderr(Box::new(log_stream.clone()));
Self {
wasi,
wasi_output,
log_stream,
..Default::default()
}
}
Expand Down Expand Up @@ -78,7 +88,7 @@ impl Runner {
Self { wasm, linker }
}

pub fn exec(&mut self, input: Vec<u8>) -> Result<Vec<u8>> {
pub fn exec(&mut self, input: Vec<u8>) -> Result<(Vec<u8>, Vec<u8>)> {
let mut store = Store::new(self.linker.engine(), StoreContext::new(input));

let module = Module::from_binary(self.linker.engine(), &self.wasm)?;
Expand All @@ -89,11 +99,17 @@ impl Runner {
run.call(&mut store, ())?;
let store_context = store.into_data();
drop(store_context.wasi);
Ok(store_context
let logs = store_context
.log_stream
.try_into_inner()
.expect("log stream reference still exists")
.into_inner();
let output = store_context
.wasi_output
.try_into_inner()
.expect("Output stream reference still exists")
.into_inner())
.into_inner();
Ok((output, logs))
}
}

Expand Down
7 changes: 7 additions & 0 deletions crates/cli/tests/sample-scripts/logging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var Shopify = {
main: (i) => {
console.log("hello world from console.log");
console.error("hello world from console.error");
return i;
}
}
4 changes: 3 additions & 1 deletion crates/core/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ static SCRIPT_NAME: &str = "script.js";
pub extern "C" fn init() {
unsafe {
let mut context = Context::default();
context.register_globals(io::stdout()).unwrap();
context
.register_globals(io::stderr(), io::stderr())
.unwrap();

let mut contents = String::new();
io::stdin().read_to_string(&mut contents).unwrap();
Expand Down
23 changes: 21 additions & 2 deletions crates/quickjs-wasm-rs/src/js_binding/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,16 @@ impl Context {
Value::new(self.inner, raw)
}

pub fn register_globals<T>(&mut self, log_stream: T) -> Result<()>
pub fn register_globals<T>(&mut self, log_stream: T, error_stream: T) -> Result<()>
where
T: Write,
{
let console_log_callback = unsafe { self.new_callback(console_log_to(log_stream))? };
let console_error_callback = unsafe { self.new_callback(console_log_to(error_stream))? };
let global_object = self.global_object()?;
let console_object = self.object_value()?;
console_object.set_property("log", console_log_callback)?;
console_object.set_property("error", console_error_callback)?;
global_object.set_property("console", console_object)?;
Ok(())
}
Expand Down Expand Up @@ -348,7 +350,7 @@ mod tests {
let mut stream = SharedStream::default();

let mut ctx = Context::default();
ctx.register_globals(stream.clone())?;
ctx.register_globals(stream.clone(), stream.clone())?;

ctx.eval_global("main", "console.log(\"hello world\");")?;
assert_eq!(b"hello world\n", stream.0.borrow().as_slice());
Expand All @@ -359,4 +361,21 @@ mod tests {
assert_eq!(b"bonjour le monde\n", stream.0.borrow().as_slice());
Ok(())
}

#[test]
fn test_console_error() -> Result<()> {
let mut stream = SharedStream::default();

let mut ctx = Context::default();
ctx.register_globals(stream.clone(), stream.clone())?;

ctx.eval_global("main", "console.error(\"hello world\");")?;
assert_eq!(b"hello world\n", stream.0.borrow().as_slice());

stream.clear();

ctx.eval_global("main", "console.error(\"bonjour\", \"le\", \"monde\")")?;
assert_eq!(b"bonjour le monde\n", stream.0.borrow().as_slice());
Ok(())
}
}

0 comments on commit e7712e9

Please sign in to comment.