Skip to content

Commit 3a9ac87

Browse files
committed
Store context as singleton and with global reference
1 parent f2a483f commit 3a9ac87

File tree

1 file changed

+22
-3
lines changed

1 file changed

+22
-3
lines changed

provider/src/lib.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,22 @@ pub mod write;
55

66
use rmp::encode::ByteBuf;
77
use shopify_function_wasm_api_core::ContextPtr;
8-
use std::ptr::NonNull;
8+
use std::{cell::RefCell, ptr::NonNull};
99
use string_interner::StringInterner;
1010
use write::State;
1111

1212
pub const PROVIDER_MODULE_NAME: &str =
1313
concat!("shopify_function_v", env!("CARGO_PKG_VERSION_MAJOR"));
1414

15+
// This serves 2 purposes:
16+
// 1. Creating multiple contexts in Wasm won't cause a hang waiting for input
17+
// on stdin.
18+
// 2. Data in the context can be read by the host environment.
19+
// Thread local values live for the same amount of time as the Wasm instance.
20+
thread_local! {
21+
static CONTEXT: RefCell<Option<ContextPtr>> = const { RefCell::new(None) };
22+
}
23+
1524
#[cfg(target_pointer_width = "64")]
1625
type DoubleUsize = u128;
1726
#[cfg(target_pointer_width = "32")]
@@ -93,12 +102,22 @@ pub(crate) use decorate_for_target;
93102
#[cfg(target_family = "wasm")]
94103
#[export_name = "_shopify_function_context_new"]
95104
extern "C" fn shopify_function_context_new() -> ContextPtr {
96-
Box::into_raw(Box::new(Context::new_from_stdin())) as _
105+
// Assuming this is called from a Wasm module, we should return a
106+
// pre-existing context if there is one to avoid trying to read input
107+
// multiple times.
108+
CONTEXT.with_borrow_mut(|option_ptr| {
109+
*option_ptr.get_or_insert_with(|| Box::into_raw(Box::new(Context::new_from_stdin())) as _)
110+
})
97111
}
98112

99113
#[cfg(not(target_family = "wasm"))]
100114
pub fn shopify_function_context_new_from_msgpack_bytes(bytes: Vec<u8>) -> ContextPtr {
101-
Box::into_raw(Box::new(Context::new(bytes))) as _
115+
// Assuming this is called from a unit test, we should reset the context
116+
// with the input passed as an argument instead of using any context that
117+
// may have been present before.
118+
CONTEXT.with_borrow_mut(|option_ptr| {
119+
*option_ptr.insert(Box::into_raw(Box::new(Context::new(bytes))) as _)
120+
})
102121
}
103122

104123
decorate_for_target! {

0 commit comments

Comments
 (0)