From 011a442f31403101feba53c51032c670a5607945 Mon Sep 17 00:00:00 2001 From: Mehdi Salemi Date: Wed, 2 Apr 2025 13:48:04 -0400 Subject: [PATCH 1/7] adds shopify function provider --- build.rs | 1 + providers/shopify_function_v0.0.1.wasm | Bin 0 -> 121539 bytes 2 files changed, 1 insertion(+) create mode 100755 providers/shopify_function_v0.0.1.wasm diff --git a/build.rs b/build.rs index b8a7c775..b7cc054c 100644 --- a/build.rs +++ b/build.rs @@ -3,4 +3,5 @@ fn main() { println!("cargo:rerun-if-changed=providers/javy_quickjs_provider_v2.wasm"); println!("cargo:rerun-if-changed=providers/javy_quickjs_provider_v3.wasm"); println!("cargo:rerun-if-changed=providers/shopify_functions_javy_v1.wasm"); + println!("cargo:rerun-if-changed=providers/shopify_function_v0.0.1.wasm"); } diff --git a/providers/shopify_function_v0.0.1.wasm b/providers/shopify_function_v0.0.1.wasm new file mode 100755 index 0000000000000000000000000000000000000000..3c4b9c2f4193716130a288175a7f40d96840437c GIT binary patch literal 121539 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 $=YCDOQ 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 qvc80e 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 Date: Wed, 2 Apr 2025 13:49:11 -0400 Subject: [PATCH 2/7] support functions using wasm api provider --- src/engine.rs | 92 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 14 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index f7f68602..bac891a3 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -20,6 +20,17 @@ pub struct ProfileOpts { #[folder = "providers/"] struct StandardProviders; +// The prefix that identifies the Wasm API provider +const WASM_API_PROVIDER_PREFIX: &str = "shopify_function_wasm_api_provider_v"; + +// Check if the module uses the Wasm API provider +fn uses_wasm_api_provider(module: &Module) -> bool { + eprintln!("!!! module imports: !!!"); + module + .imports() + .any(|i| i.module().starts_with(WASM_API_PROVIDER_PREFIX)) +} + fn import_modules( module: &Module, engine: &Engine, @@ -28,7 +39,10 @@ fn import_modules( ) { let imported_modules: HashSet = module.imports().map(|i| i.module().to_string()).collect(); + imported_modules.iter().for_each(|module_name| { + eprintln!("!!! module name: !!!"); + eprintln!("module_name: {:?}", module_name); let imported_module_bytes = StandardProviders::get(&format!("{module_name}.wasm")); if let Some(bytes) = imported_module_bytes { @@ -126,7 +140,19 @@ pub fn run(params: FunctionRunParams) -> Result { let module = Module::from_file(&engine, &function_path) .map_err(|e| anyhow!("Couldn't load the Function {:?}: {}", &function_path, e))?; - let input_stream = wasi_common::pipe::ReadPipe::new(Cursor::new(input.clone())); + // Check if we need to use MessagePack transcoding + let uses_msgpack = uses_wasm_api_provider(&module); + let processed_input = if uses_msgpack { + // If this module uses the Wasm API provider, convert JSON to MessagePack + let json = serde_json::from_slice::(&input) + .map_err(|e| anyhow!("Invalid input JSON for Wasm API function: {}", e))?; + rmp_serde::to_vec(&json) + .map_err(|e| anyhow!("Couldn't convert JSON to MessagePack: {}", e))? + } else { + input.clone() + }; + + let input_stream = wasi_common::pipe::ReadPipe::new(Cursor::new(processed_input)); let output_stream = wasi_common::pipe::WritePipe::new_in_memory(); let error_stream = wasi_common::pipe::WritePipe::new_in_memory(); @@ -203,24 +229,49 @@ pub fn run(params: FunctionRunParams) -> Result { .expect("Output stream reference still exists") .into_inner(); - let output: FunctionOutput = match serde_json::from_slice(&raw_output) { - Ok(json_output) => JsonOutput(json_output), - Err(error) => InvalidJsonOutput(InvalidOutput { - stdout: std::str::from_utf8(&raw_output) - .map_err(|e| anyhow!("Couldn't print Function Output: {}", e)) - .unwrap() - .to_owned(), - error: error.to_string(), - }), + let output: FunctionOutput = if uses_msgpack { + // If using MessagePack, decode the output from MessagePack to JSON + match rmp_serde::from_slice::(&raw_output) { + Ok(json_output) => JsonOutput(json_output), + Err(error) => { + // If MessagePack decoding fails, try direct JSON decode as a fallback + match serde_json::from_slice(&raw_output) { + Ok(json_output) => JsonOutput(json_output), + Err(_) => InvalidJsonOutput(InvalidOutput { + stdout: std::str::from_utf8(&raw_output) + .map_err(|e| anyhow!("Couldn't print Function Output: {}", e)) + .unwrap() + .to_owned(), + error: error.to_string(), + }), + } + } + } + } else { + // If not using MessagePack, handle as normal JSON + match serde_json::from_slice(&raw_output) { + Ok(json_output) => JsonOutput(json_output), + Err(error) => InvalidJsonOutput(InvalidOutput { + stdout: std::str::from_utf8(&raw_output) + .map_err(|e| anyhow!("Couldn't print Function Output: {}", e)) + .unwrap() + .to_owned(), + error: error.to_string(), + }), + } }; let name = function_path.file_name().unwrap().to_str().unwrap(); let size = function_path.metadata()?.len() / 1024; - let parsed_input = - String::from_utf8(input).map_err(|e| anyhow!("Couldn't parse input: {}", e))?; - - let function_run_input = serde_json::from_str(&parsed_input)?; + let function_run_input = if uses_msgpack { + // For display purposes, we want to show the original JSON input + serde_json::from_slice(&input)? + } else { + String::from_utf8(input) + .map_err(|e| anyhow!("Couldn't parse input: {}", e)) + .and_then(|s| serde_json::from_str(&s).map_err(Into::into))? + }; let function_run_result = FunctionRunResult { name: name.to_string(), @@ -383,4 +434,17 @@ mod tests { file_path.metadata().unwrap().len() / 1024 ); } + + #[test] + fn test_wasm_api_provider_detection() { + let module_path = Path::new("tests/fixtures/build/js_function.wasm"); + let module = Module::from_file(&Engine::default(), module_path).unwrap(); + assert!(!uses_wasm_api_provider(&module)); + + // This test will only pass if you have a test function compiled with the wasm api provider + // If this test fails, you may need to create such a test fixture. + // let wasm_api_module_path = Path::new("tests/fixtures/build/wasm_api_function.wasm"); + // let wasm_api_module = Module::from_file(&Engine::default(), wasm_api_module_path).unwrap(); + // assert!(uses_wasm_api_provider(&wasm_api_module)); + } } From 1e39db3009fd99af84ea143a66eb31d7cea61544 Mon Sep 17 00:00:00 2001 From: Mehdi Salemi Date: Wed, 2 Apr 2025 13:52:15 -0400 Subject: [PATCH 3/7] nits --- src/engine.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index bac891a3..25a4948e 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -20,10 +20,8 @@ pub struct ProfileOpts { #[folder = "providers/"] struct StandardProviders; -// The prefix that identifies the Wasm API provider const WASM_API_PROVIDER_PREFIX: &str = "shopify_function_wasm_api_provider_v"; -// Check if the module uses the Wasm API provider fn uses_wasm_api_provider(module: &Module) -> bool { eprintln!("!!! module imports: !!!"); module From 0242cf0243dff9f07e050577a1e836effc53a01a Mon Sep 17 00:00:00 2001 From: Mehdi Salemi Date: Wed, 2 Apr 2025 14:12:43 -0400 Subject: [PATCH 4/7] working --- src/engine.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 25a4948e..e9be8705 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -20,13 +20,14 @@ pub struct ProfileOpts { #[folder = "providers/"] struct StandardProviders; -const WASM_API_PROVIDER_PREFIX: &str = "shopify_function_wasm_api_provider_v"; +const WASM_API_PROVIDER_PREFIX: &str = "shopify_function_v"; fn uses_wasm_api_provider(module: &Module) -> bool { - eprintln!("!!! module imports: !!!"); module .imports() - .any(|i| i.module().starts_with(WASM_API_PROVIDER_PREFIX)) + .any(|i| { + i.module().starts_with(WASM_API_PROVIDER_PREFIX) + }) } fn import_modules( @@ -39,8 +40,6 @@ fn import_modules( module.imports().map(|i| i.module().to_string()).collect(); imported_modules.iter().for_each(|module_name| { - eprintln!("!!! module name: !!!"); - eprintln!("module_name: {:?}", module_name); let imported_module_bytes = StandardProviders::get(&format!("{module_name}.wasm")); if let Some(bytes) = imported_module_bytes { @@ -138,15 +137,15 @@ pub fn run(params: FunctionRunParams) -> Result { let module = Module::from_file(&engine, &function_path) .map_err(|e| anyhow!("Couldn't load the Function {:?}: {}", &function_path, e))?; - // Check if we need to use MessagePack transcoding let uses_msgpack = uses_wasm_api_provider(&module); + let processed_input = if uses_msgpack { - // If this module uses the Wasm API provider, convert JSON to MessagePack let json = serde_json::from_slice::(&input) - .map_err(|e| anyhow!("Invalid input JSON for Wasm API function: {}", e))?; + .map_err(|e| anyhow!("Invalid input JSON for function: {}", e))?; + rmp_serde::to_vec(&json) .map_err(|e| anyhow!("Couldn't convert JSON to MessagePack: {}", e))? - } else { + } else { input.clone() }; From a5f38b90a8b8d14ba74e718530273f01e621146b Mon Sep 17 00:00:00 2001 From: Mehdi Salemi Date: Wed, 2 Apr 2025 14:26:44 -0400 Subject: [PATCH 5/7] nits2 - working, news test --- src/engine.rs | 85 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 23 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index e9be8705..3eba4f6e 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -227,34 +227,38 @@ pub fn run(params: FunctionRunParams) -> Result { .into_inner(); let output: FunctionOutput = if uses_msgpack { - // If using MessagePack, decode the output from MessagePack to JSON - match rmp_serde::from_slice::(&raw_output) { - Ok(json_output) => JsonOutput(json_output), - Err(error) => { - // If MessagePack decoding fails, try direct JSON decode as a fallback - match serde_json::from_slice(&raw_output) { - Ok(json_output) => JsonOutput(json_output), - Err(_) => InvalidJsonOutput(InvalidOutput { - stdout: std::str::from_utf8(&raw_output) - .map_err(|e| anyhow!("Couldn't print Function Output: {}", e)) - .unwrap() - .to_owned(), - error: error.to_string(), - }), + if !raw_output.is_empty() { + let might_be_text = raw_output.iter().all(|&b| b >= 32 && b <= 126); + let text_starts_with_letter = raw_output.get(0).map_or(false, |&b| (b >= b'a' && b <= b'z') || (b >= b'A' && b <= b'Z')); + + if might_be_text && text_starts_with_letter { + match std::str::from_utf8(&raw_output) { + Ok(text) => JsonOutput(serde_json::Value::String(text.to_owned())), + Err(_) => try_parse_as_msgpack(&raw_output) } + } else { + try_parse_as_msgpack(&raw_output) } + } else { + JsonOutput(serde_json::Value::Null) } } else { - // If not using MessagePack, handle as normal JSON match serde_json::from_slice(&raw_output) { Ok(json_output) => JsonOutput(json_output), - Err(error) => InvalidJsonOutput(InvalidOutput { - stdout: std::str::from_utf8(&raw_output) - .map_err(|e| anyhow!("Couldn't print Function Output: {}", e)) - .unwrap() - .to_owned(), - error: error.to_string(), - }), + Err(error) => { + let text_output = std::str::from_utf8(&raw_output); + match text_output { + Ok(text) if !text.is_empty() => { + JsonOutput(serde_json::Value::String(text.to_owned())) + }, + _ => { + InvalidJsonOutput(InvalidOutput { + stdout: String::from_utf8_lossy(&raw_output).into_owned(), + error: error.to_string(), + }) + } + } + } } }; @@ -262,7 +266,6 @@ pub fn run(params: FunctionRunParams) -> Result { let size = function_path.metadata()?.len() / 1024; let function_run_input = if uses_msgpack { - // For display purposes, we want to show the original JSON input serde_json::from_slice(&input)? } else { String::from_utf8(input) @@ -286,6 +289,42 @@ pub fn run(params: FunctionRunParams) -> Result { Ok(function_run_result) } +fn try_parse_as_msgpack(raw_output: &[u8]) -> FunctionOutput { + match rmp_serde::from_slice::(raw_output) { + Ok(json_output) => { + // If we get a number that matches the first byte's ASCII value, it's likely text + if let Some(n) = json_output.as_u64() { + if n < 127 && raw_output.len() > 1 && raw_output[0] as u64 == n { + // This is likely text being misinterpreted as a number + return JsonOutput(serde_json::Value::String( + String::from_utf8_lossy(raw_output).into_owned() + )); + } + } + JsonOutput(json_output) + }, + Err(error) => { + match serde_json::from_slice(raw_output) { + Ok(json_output) => JsonOutput(json_output), + Err(_) => { + let text_output = std::str::from_utf8(raw_output); + match text_output { + Ok(text) => { + JsonOutput(serde_json::Value::String(text.to_owned())) + }, + Err(_) => { + InvalidJsonOutput(InvalidOutput { + stdout: String::from_utf8_lossy(raw_output).into_owned(), + error: error.to_string(), + }) + } + } + } + } + } + } +} + #[cfg(test)] mod tests { use colored::Colorize; From 8e0e6194237a7f029e7ea5c7cb4465c06dd8b8f1 Mon Sep 17 00:00:00 2001 From: Mehdi Salemi Date: Wed, 2 Apr 2025 14:28:54 -0400 Subject: [PATCH 6/7] add fixtures --- src/engine.rs | 9 +++---- .../build/wasm_api_function.merged.wasm | Bin 0 -> 87680 bytes .../input/wasm_api_function_input.json | 24 ++++++++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 tests/fixtures/build/wasm_api_function.merged.wasm create mode 100644 tests/fixtures/input/wasm_api_function_input.json diff --git a/src/engine.rs b/src/engine.rs index 3eba4f6e..0bbd8b11 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -292,7 +292,6 @@ pub fn run(params: FunctionRunParams) -> Result { fn try_parse_as_msgpack(raw_output: &[u8]) -> FunctionOutput { match rmp_serde::from_slice::(raw_output) { Ok(json_output) => { - // If we get a number that matches the first byte's ASCII value, it's likely text if let Some(n) = json_output.as_u64() { if n < 127 && raw_output.len() > 1 && raw_output[0] as u64 == n { // This is likely text being misinterpreted as a number @@ -477,10 +476,8 @@ mod tests { let module = Module::from_file(&Engine::default(), module_path).unwrap(); assert!(!uses_wasm_api_provider(&module)); - // This test will only pass if you have a test function compiled with the wasm api provider - // If this test fails, you may need to create such a test fixture. - // let wasm_api_module_path = Path::new("tests/fixtures/build/wasm_api_function.wasm"); - // let wasm_api_module = Module::from_file(&Engine::default(), wasm_api_module_path).unwrap(); - // assert!(uses_wasm_api_provider(&wasm_api_module)); + let wasm_api_module_path = Path::new("tests/fixtures/build/wasm_api_function.merged.wasm"); + let wasm_api_module = Module::from_file(&Engine::default(), wasm_api_module_path).unwrap(); + assert!(uses_wasm_api_provider(&wasm_api_module)); } } diff --git a/tests/fixtures/build/wasm_api_function.merged.wasm b/tests/fixtures/build/wasm_api_function.merged.wasm new file mode 100644 index 0000000000000000000000000000000000000000..560d41c338389655c24513056deeb7bc5931db04 GIT binary patch literal 87680 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 literal 0 HcmV?d00001 diff --git a/tests/fixtures/input/wasm_api_function_input.json b/tests/fixtures/input/wasm_api_function_input.json new file mode 100644 index 00000000..5e4177f4 --- /dev/null +++ b/tests/fixtures/input/wasm_api_function_input.json @@ -0,0 +1,24 @@ +{ + "cart": { + "lines": [ + { + "merchandise": { + "id": "gid://shopify/ProductVariant/1", + "title": "Sample Product" + }, + "quantity": 2, + "cost": { + "totalAmount": { + "amount": "24.99", + "currencyCode": "USD" + } + } + } + ] + }, + "discounts": { + "metafield": { + "value": "{\"percentage\":20,\"applicable_items\":[\"gid://shopify/ProductVariant/1\"]}" + } + } +} \ No newline at end of file From 47888b0299599ba1ee8ef4afdb69099b4ba06b58 Mon Sep 17 00:00:00 2001 From: Mehdi Salemi Date: Thu, 3 Apr 2025 11:26:29 -0400 Subject: [PATCH 7/7] cleanup --- src/engine.rs | 98 +++++++++++++++++++++++++-------------------------- src/main.rs | 1 + 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 0bbd8b11..cfc8f093 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -63,6 +63,7 @@ pub struct FunctionRunParams<'a> { pub export: &'a str, pub profile_opts: Option<&'a ProfileOpts>, pub scale_factor: f64, + pub use_msgpack: bool, } const STARTING_FUEL: u64 = u64::MAX; @@ -125,6 +126,7 @@ pub fn run(params: FunctionRunParams) -> Result { export, profile_opts, scale_factor, + use_msgpack, } = params; let engine = Engine::new( @@ -137,15 +139,19 @@ pub fn run(params: FunctionRunParams) -> Result { let module = Module::from_file(&engine, &function_path) .map_err(|e| anyhow!("Couldn't load the Function {:?}: {}", &function_path, e))?; - let uses_msgpack = uses_wasm_api_provider(&module); + let uses_wasm_api = if use_msgpack { + true + } else { + uses_wasm_api_provider(&module) + }; - let processed_input = if uses_msgpack { + let processed_input = if use_msgpack { let json = serde_json::from_slice::(&input) .map_err(|e| anyhow!("Invalid input JSON for function: {}", e))?; - + rmp_serde::to_vec(&json) .map_err(|e| anyhow!("Couldn't convert JSON to MessagePack: {}", e))? - } else { + } else { input.clone() }; @@ -226,37 +232,22 @@ pub fn run(params: FunctionRunParams) -> Result { .expect("Output stream reference still exists") .into_inner(); - let output: FunctionOutput = if uses_msgpack { - if !raw_output.is_empty() { - let might_be_text = raw_output.iter().all(|&b| b >= 32 && b <= 126); - let text_starts_with_letter = raw_output.get(0).map_or(false, |&b| (b >= b'a' && b <= b'z') || (b >= b'A' && b <= b'Z')); - - if might_be_text && text_starts_with_letter { - match std::str::from_utf8(&raw_output) { - Ok(text) => JsonOutput(serde_json::Value::String(text.to_owned())), - Err(_) => try_parse_as_msgpack(&raw_output) - } - } else { - try_parse_as_msgpack(&raw_output) - } - } else { + let output: FunctionOutput = if uses_wasm_api { + if raw_output.is_empty() { JsonOutput(serde_json::Value::Null) + } else { + try_parse_as_msgpack(&raw_output) } } else { match serde_json::from_slice(&raw_output) { Ok(json_output) => JsonOutput(json_output), Err(error) => { - let text_output = std::str::from_utf8(&raw_output); - match text_output { - Ok(text) if !text.is_empty() => { - JsonOutput(serde_json::Value::String(text.to_owned())) - }, - _ => { - InvalidJsonOutput(InvalidOutput { - stdout: String::from_utf8_lossy(&raw_output).into_owned(), - error: error.to_string(), - }) - } + match std::str::from_utf8(&raw_output) { + Ok(text) if !text.is_empty() => JsonOutput(serde_json::Value::String(text.to_owned())), + _ => InvalidJsonOutput(InvalidOutput { + stdout: String::from_utf8_lossy(&raw_output).into_owned(), + error: error.to_string(), + }) } } } @@ -265,7 +256,7 @@ pub fn run(params: FunctionRunParams) -> Result { let name = function_path.file_name().unwrap().to_str().unwrap(); let size = function_path.metadata()?.len() / 1024; - let function_run_input = if uses_msgpack { + let function_run_input = if uses_wasm_api { serde_json::from_slice(&input)? } else { String::from_utf8(input) @@ -290,11 +281,19 @@ pub fn run(params: FunctionRunParams) -> Result { } fn try_parse_as_msgpack(raw_output: &[u8]) -> FunctionOutput { + if !raw_output.is_empty() { + let first_char = raw_output[0] as char; + if first_char == '{' || first_char == '[' { + if let Ok(json_output) = serde_json::from_slice(raw_output) { + return JsonOutput(json_output); + } + } + } + match rmp_serde::from_slice::(raw_output) { Ok(json_output) => { if let Some(n) = json_output.as_u64() { if n < 127 && raw_output.len() > 1 && raw_output[0] as u64 == n { - // This is likely text being misinterpreted as a number return JsonOutput(serde_json::Value::String( String::from_utf8_lossy(raw_output).into_owned() )); @@ -302,24 +301,11 @@ fn try_parse_as_msgpack(raw_output: &[u8]) -> FunctionOutput { } JsonOutput(json_output) }, - Err(error) => { - match serde_json::from_slice(raw_output) { - Ok(json_output) => JsonOutput(json_output), - Err(_) => { - let text_output = std::str::from_utf8(raw_output); - match text_output { - Ok(text) => { - JsonOutput(serde_json::Value::String(text.to_owned())) - }, - Err(_) => { - InvalidJsonOutput(InvalidOutput { - stdout: String::from_utf8_lossy(raw_output).into_owned(), - error: error.to_string(), - }) - } - } - } - } + Err(msgpack_error) => { + InvalidJsonOutput(InvalidOutput { + stdout: String::from_utf8_lossy(raw_output).into_owned(), + error: msgpack_error.to_string(), + }) } } } @@ -480,4 +466,18 @@ mod tests { let wasm_api_module = Module::from_file(&Engine::default(), wasm_api_module_path).unwrap(); assert!(uses_wasm_api_provider(&wasm_api_module)); } + + #[test] + fn test_wasm_api_function() { + let input = include_bytes!("../tests/fixtures/input/wasm_api_function_input.json").to_vec(); + let function_run_result = run(FunctionRunParams { + function_path: Path::new("tests/fixtures/build/wasm_api_function.merged.wasm").to_path_buf(), + input, + export: DEFAULT_EXPORT, + use_msgpack: true, + ..Default::default() + }); + + assert!(function_run_result.is_ok()); + } } diff --git a/src/main.rs b/src/main.rs index 383b2284..6012afe2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -184,6 +184,7 @@ fn main() -> Result<()> { export: opts.export.as_ref(), profile_opts: profile_opts.as_ref(), scale_factor, + use_msgpack: opts.codec == Codec::JsonToMessagepack, })?; if opts.json {