Skip to content

Stop using stdio #99

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

Draft
wants to merge 20 commits into
base: jc.singleton-take2
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

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

3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ Here's a simple example of how to use the API:

```rust
fn main(context: &mut Context) -> Result<()> {
shopify_function_wasm_api::init_panic_handler();
let input = context.input_get()?;

// Function logic

context.finalize_output()?;

Ok(())
}
```
Expand Down
3 changes: 1 addition & 2 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ thiserror = "2.0"
seq-macro = "0.3.5"

[target.'cfg(not(target_family = "wasm"))'.dependencies]
shopify_function_provider = { path = "../provider", version = "1.0.1" }
shopify_function_provider = { path = "../provider", version = "2.0.0" }
serde_json = "1.0"
rmp-serde = "1.3"

Expand All @@ -33,4 +33,3 @@ path = "examples/cart-checkout-validation-wasm-api.rs"
[[example]]
name = "cart-checkout-validation-wasi-json"
path = "examples/cart-checkout-validation-wasi-json.rs"

3 changes: 1 addition & 2 deletions api/examples/cart-checkout-validation-wasm-api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use shopify_function_wasm_api::{Context, Value};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
shopify_function_wasm_api::init_panic_handler();
let mut context = Context::new();

let input = context.input_get()?;
Expand Down Expand Up @@ -38,8 +39,6 @@ fn main() -> Result<(), Box<dyn Error>> {
1,
)?;

context.finalize_output()?;

Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion api/examples/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ use shopify_function_wasm_api::{
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
shopify_function_wasm_api::init_panic_handler();
let mut context = Context::new();
let input = context.input_get()?;

let value = Value::deserialize(&input)?;
let result = echo(value);
result.serialize(&mut context)?;
context.finalize_output()?;

Ok(())
}
Expand Down
14 changes: 14 additions & 0 deletions api/examples/log-len.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use std::error::Error;

use shopify_function_wasm_api::Context;

fn main() -> Result<(), Box<dyn Error>> {
shopify_function_wasm_api::init_panic_handler();
let mut context = Context::new();
let input = context.input_get()?;
let len = input.as_number().unwrap() as usize;
for _ in 0..len / 100 {
context.log(&"a".repeat(100));
}
Ok(())
}
11 changes: 11 additions & 0 deletions api/examples/log-past-capacity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use std::error::Error;

use shopify_function_wasm_api::Context;

fn main() -> Result<(), Box<dyn Error>> {
shopify_function_wasm_api::init_panic_handler();
let mut context = Context::new();
context.log(&"a".repeat(1020));
context.log(&"b".repeat(10));
Ok(())
}
13 changes: 13 additions & 0 deletions api/examples/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::error::Error;

use shopify_function_wasm_api::Context;

fn main() -> Result<(), Box<dyn Error>> {
shopify_function_wasm_api::init_panic_handler();
let mut context = Context::new();
context.log("Hi!\n");
context.log("Hello\n");
context.log("Here's a third string\n");
context.log("✌️\n");
Ok(())
}
8 changes: 8 additions & 0 deletions api/examples/panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::error::Error;

use shopify_function_wasm_api::init_panic_handler;

fn main() -> Result<(), Box<dyn Error>> {
init_panic_handler();
panic!("at the disco");
}
41 changes: 30 additions & 11 deletions api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
//! use std::error::Error;
//!
//! fn main() -> Result<(), Box<dyn Error>> {
//! shopify_function_wasm_api::init_panic_handler();
//! let mut context = Context::new();
//! let input = context.input_get()?;
//! let value: i32 = Deserialize::deserialize(&input)?;
//! value.serialize(&mut context)?;
//! context.finalize_output()?;
//! Ok(())
//! }
//! ```
Expand All @@ -23,18 +23,16 @@
use shopify_function_wasm_api_core::read::{ErrorCode, NanBox, Val, ValueRef};
use std::sync::atomic::{AtomicUsize, Ordering};

pub mod log;
pub mod read;
pub mod write;

pub use read::Deserialize;
pub use write::Serialize;

#[cfg(target_family = "wasm")]
#[link(wasm_import_module = "shopify_function_v1")]
#[link(wasm_import_module = "shopify_function_v2")]
extern "C" {
// Common API.
fn shopify_function_context_new();

// Read API.
fn shopify_function_input_get() -> Val;
fn shopify_function_input_get_val_len(scope: Val) -> usize;
Expand All @@ -50,7 +48,6 @@ extern "C" {
// Write API.
fn shopify_function_output_new_bool(bool: u32) -> usize;
fn shopify_function_output_new_null() -> usize;
fn shopify_function_output_finalize() -> usize;
fn shopify_function_output_new_i32(int: i32) -> usize;
fn shopify_function_output_new_f64(float: f64) -> usize;
fn shopify_function_output_new_utf8_str(ptr: *const u8, len: usize) -> usize;
Expand All @@ -62,6 +59,9 @@ extern "C" {
fn shopify_function_output_new_array(len: usize) -> usize;
fn shopify_function_output_finish_array() -> usize;

// Log API.
fn shopify_function_log_new_utf8_str(ptr: *const u8, len: usize);

// Other.
fn shopify_function_intern_utf8_str(ptr: *const u8, len: usize) -> usize;
}
Expand Down Expand Up @@ -119,9 +119,6 @@ mod provider_fallback {
pub(crate) unsafe fn shopify_function_output_new_null() -> usize {
shopify_function_provider::write::shopify_function_output_new_null() as usize
}
pub(crate) unsafe fn shopify_function_output_finalize() -> usize {
shopify_function_provider::write::shopify_function_output_finalize() as usize
}
pub(crate) unsafe fn shopify_function_output_new_i32(int: i32) -> usize {
shopify_function_provider::write::shopify_function_output_new_i32(int) as usize
}
Expand Down Expand Up @@ -155,6 +152,20 @@ mod provider_fallback {
shopify_function_provider::write::shopify_function_output_finish_array() as usize
}

// Logging.
pub(crate) unsafe fn shopify_function_log_new_utf8_str(ptr: *const u8, len: usize) {
let addr = shopify_function_provider::log::shopify_function_log_new_utf8_str(len)
as *const [usize; 5];
let array = *addr;
let source_offset = array[0];
let dst_offset1 = array[1];
let len1 = array[2];
let dst_offset2 = array[3];
let len2 = array[4];
std::ptr::copy(ptr.add(source_offset) as _, dst_offset1 as _, len1);
std::ptr::copy(ptr.add(source_offset).add(len1), dst_offset2 as _, len2);
}

// Other.
pub(crate) unsafe fn shopify_function_intern_utf8_str(ptr: *const u8, len: usize) -> usize {
let result = shopify_function_provider::shopify_function_intern_utf8_str(len);
Expand Down Expand Up @@ -408,7 +419,6 @@ impl Context {

#[cfg(target_family = "wasm")]
{
unsafe { shopify_function_context_new() };
Self
}
}
Expand All @@ -419,7 +429,7 @@ impl Context {
#[cfg(not(target_family = "wasm"))]
pub fn new_with_input(input: serde_json::Value) -> Self {
let bytes = rmp_serde::to_vec(&input).unwrap();
shopify_function_provider::shopify_function_context_new_from_msgpack_bytes(bytes);
shopify_function_provider::initialize_from_msgpack_bytes(bytes);
Self
}

Expand Down Expand Up @@ -448,6 +458,15 @@ impl Default for Context {
}
}

/// Configures panics to write to the logging API.
pub fn init_panic_handler() {
#[cfg(target_family = "wasm")]
std::panic::set_hook(Box::new(|info| {
let message = format!("{info}");
log::log_utf8_str(&message);
}));
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
14 changes: 14 additions & 0 deletions api/src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! The log API for the Shopify Function Wasm API.

use crate::Context;

pub(super) fn log_utf8_str(message: &str) {
unsafe { crate::shopify_function_log_new_utf8_str(message.as_ptr(), message.len()) };
}

impl Context {
/// Log `message`.
pub fn log(&mut self, message: &str) {
log_utf8_str(message)
}
}
27 changes: 10 additions & 17 deletions api/src/shopify_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ typedef size_t InternedStringId;
#define WRITE_RESULT_ERROR 1

// Import module declaration
#define SHOPIFY_FUNCTION_IMPORT_MODULE "shopify_function_v1"

// Common API
/**
* Creates a new context for the Shopify Function execution
*/
__attribute__((import_module(SHOPIFY_FUNCTION_IMPORT_MODULE)))
__attribute__((import_name("shopify_function_context_new")))
extern void shopify_function_context_new(void);
#define SHOPIFY_FUNCTION_IMPORT_MODULE "shopify_function_v2"

// Read API
/**
Expand Down Expand Up @@ -111,14 +103,6 @@ __attribute__((import_module(SHOPIFY_FUNCTION_IMPORT_MODULE)))
__attribute__((import_name("shopify_function_output_new_null")))
extern WriteResult shopify_function_output_new_null();

/**
* Finalizes the output and returns the result
* @return WriteResult indicating success or failure
*/
__attribute__((import_module(SHOPIFY_FUNCTION_IMPORT_MODULE)))
__attribute__((import_name("shopify_function_output_finalize")))
extern WriteResult shopify_function_output_finalize();

/**
* Creates a new 32-bit integer output value
* @param value The integer value
Expand Down Expand Up @@ -201,4 +185,13 @@ __attribute__((import_module(SHOPIFY_FUNCTION_IMPORT_MODULE)))
__attribute__((import_name("shopify_function_intern_utf8_str")))
extern InternedStringId shopify_function_intern_utf8_str(const uint8_t* ptr, size_t len);

/**
* Logs a new UTF-8 string output value
* @param ptr The string data
* @param len The length of the string
*/
__attribute__((import_module(SHOPIFY_FUNCTION_IMPORT_MODULE)))
__attribute__((import_name("shopify_function_log_new_utf8_str")))
extern void shopify_function_log_new_utf8_str(const uint8_t* ptr, size_t len);

#endif // SHOPIFY_FUNCTION_H
Loading