-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
putting a lot of error infrastructure into place in the Rust stable c…
…rate
- Loading branch information
Showing
19 changed files
with
179 additions
and
152 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 0 additions & 44 deletions
44
...build/stable/commands/compile/wasm_binary/rust/stable_canister_template/src/azle_error.rs
This file was deleted.
Oops, something went wrong.
76 changes: 40 additions & 36 deletions
76
src/build/stable/commands/compile/wasm_binary/rust/stable_canister_template/src/candid.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,74 @@ | ||
use std::error::Error; | ||
|
||
use crate::{ | ||
ic, quickjs_with_ctx, wasm_binary_manipulation::get_js_code, CONTEXT_REF_CELL, MODULE_NAME, | ||
error::{handle_promise_error, quickjs_call_with_error_handling}, | ||
ic, quickjs_with_ctx, | ||
wasm_binary_manipulation::get_js_code, | ||
CONTEXT_REF_CELL, MODULE_NAME, | ||
}; | ||
use std::error::Error; | ||
|
||
#[no_mangle] | ||
pub fn get_candid_and_method_meta_pointer() -> *mut std::os::raw::c_char { | ||
std::panic::set_hook(Box::new(|panic_info| { | ||
let msg = if let Some(s) = panic_info.payload().downcast_ref::<&str>() { | ||
*s | ||
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() { | ||
s.as_str() | ||
} else { | ||
"Unknown panic message" | ||
}; | ||
|
||
let location = if let Some(location) = panic_info.location() { | ||
format!(" at {}:{}", location.file(), location.line()) | ||
} else { | ||
" (unknown location)".to_string() | ||
}; | ||
|
||
let message = &format!("Panic occurred: {}{}", msg, location); | ||
|
||
ic_cdk::println!("{}", message); | ||
})); | ||
type CCharPtr = *mut std::os::raw::c_char; | ||
|
||
#[no_mangle] | ||
pub fn get_candid_and_method_meta_pointer() -> CCharPtr { | ||
match initialize_and_get_candid() { | ||
Ok(c_string) => c_string, | ||
Err(e) => { | ||
ic_cdk::trap(&format!("Error during candid initialization: {}", e)); | ||
Ok(c_char_ptr) => c_char_ptr, | ||
Err(error) => { | ||
ic_cdk::trap(&format!("Azle CandidAndMethodMetaError: {}", error)); | ||
} | ||
} | ||
} | ||
|
||
fn initialize_and_get_candid() -> Result<*mut std::os::raw::c_char, Box<dyn Error>> { | ||
fn initialize_and_get_candid() -> Result<CCharPtr, Box<dyn Error>> { | ||
let runtime = rquickjs::Runtime::new()?; | ||
let context = rquickjs::Context::full(&runtime)?; | ||
|
||
CONTEXT_REF_CELL.with(|context_ref_cell| { | ||
*context_ref_cell.borrow_mut() = Some(context); | ||
}); | ||
|
||
quickjs_with_ctx(|ctx| -> Result<*mut std::os::raw::c_char, Box<dyn Error>> { | ||
quickjs_with_ctx(|ctx| -> Result<CCharPtr, Box<dyn Error>> { | ||
ctx.clone() | ||
.globals() | ||
.set("_azleNodeWasmEnvironment", true)?; | ||
|
||
ic::register(ctx.clone())?; | ||
|
||
ctx.clone() | ||
.globals() | ||
.set("exports", rquickjs::Object::new(ctx.clone())?)?; | ||
|
||
ctx.clone().globals().set("_azleExperimental", false)?; | ||
|
||
let js = get_js_code()?; | ||
ic::register(ctx.clone())?; | ||
|
||
rquickjs::Module::evaluate(ctx.clone(), MODULE_NAME, std::str::from_utf8(&js)?)?; | ||
let js = get_js_code(); | ||
|
||
let get_candid_and_method_meta: rquickjs::Function = | ||
ctx.globals().get("_azleGetCandidAndMethodMeta")?; | ||
let promise = | ||
rquickjs::Module::evaluate(ctx.clone(), MODULE_NAME, std::str::from_utf8(&js)?)?; | ||
|
||
let candid_and_method_meta: String = get_candid_and_method_meta.call(())?; | ||
handle_promise_error(ctx.clone(), promise)?; | ||
|
||
let get_candid_and_method_meta: rquickjs::Function = ctx | ||
.clone() | ||
.globals() | ||
.get("_azleGetCandidAndMethodMeta") | ||
.map_err(|e| { | ||
format!( | ||
"Failed to get globalThis._azleGetCandidAndMethodMeta: {}", | ||
e | ||
) | ||
})?; | ||
|
||
let candid_and_method_meta_js_value = | ||
quickjs_call_with_error_handling(ctx.clone(), get_candid_and_method_meta, ())?; | ||
|
||
let candid_and_method_meta: String = candid_and_method_meta_js_value | ||
.as_string() | ||
.ok_or("Failed to convert candidAndMethodMeta JS value to string")? | ||
.to_string()?; | ||
|
||
let c_string = std::ffi::CString::new(candid_and_method_meta)?; | ||
let c_char_ptr = c_string.into_raw(); | ||
|
||
Ok(c_string.into_raw()) | ||
Ok(c_char_ptr) | ||
}) | ||
} |
56 changes: 56 additions & 0 deletions
56
src/build/stable/commands/compile/wasm_binary/rust/stable_canister_template/src/error.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
use rquickjs::function::IntoArgs; | ||
|
||
use crate::quickjs_with_ctx::run_event_loop; | ||
|
||
use std::error::Error; | ||
|
||
pub fn quickjs_call_with_error_handling<'a>( | ||
ctx: rquickjs::Ctx<'a>, | ||
function: rquickjs::Function<'a>, | ||
args: impl IntoArgs<'a>, | ||
) -> Result<rquickjs::Value<'a>, Box<dyn std::error::Error>> { | ||
let result: rquickjs::Value = match function.call(args) { | ||
Ok(value) => value, | ||
Err(_) => trap_on_last_exception(ctx.clone())?, | ||
}; | ||
|
||
run_event_loop(ctx.clone()); | ||
|
||
if result.is_promise() { | ||
let promise: rquickjs::Promise = result | ||
.clone() | ||
.into_promise() | ||
.ok_or("Failed to convert function call return JS value to promise")?; | ||
handle_promise_error(ctx.clone(), promise)?; | ||
} | ||
|
||
Ok(result) | ||
} | ||
|
||
fn trap_on_last_exception<T>(ctx: rquickjs::Ctx) -> Result<T, Box<dyn std::error::Error>> { | ||
let exception: rquickjs::Exception = ctx | ||
.clone() | ||
.catch() | ||
.as_exception() | ||
.ok_or("No exception found")? | ||
.clone(); | ||
|
||
ic_cdk::trap(&exception.to_string()); | ||
} | ||
|
||
pub fn handle_promise_error( | ||
ctx: rquickjs::Ctx, | ||
promise: rquickjs::Promise, | ||
) -> Result<(), Box<dyn Error>> { | ||
run_event_loop(ctx.clone()); | ||
|
||
match promise.state() { | ||
rquickjs::promise::PromiseState::Rejected => { | ||
promise.result::<rquickjs::Value>(); // TODO is this strictly necessary? | ||
trap_on_last_exception(ctx.clone())?; | ||
} | ||
_ => {} | ||
}; | ||
|
||
Ok(()) | ||
} |
27 changes: 19 additions & 8 deletions
27
...table/commands/compile/wasm_binary/rust/stable_canister_template/src/execute_method_js.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,38 @@ | ||
use crate::quickjs_with_ctx; | ||
use std::error::Error; | ||
use crate::{error::handle_promise_error, quickjs_with_ctx}; | ||
|
||
#[no_mangle] | ||
#[allow(unused)] | ||
pub extern "C" fn execute_method_js(function_index: i32, pass_arg_data: i32) { | ||
let function_name = function_index.to_string(); | ||
let pass_arg_data = pass_arg_data == 1; | ||
|
||
if let Err(error) = quickjs_with_ctx(|ctx| -> Result<(), Box<dyn Error>> { | ||
let callbacks: rquickjs::Object = ctx.clone().globals().get("_azleCallbacks")?; | ||
let quickjs_result = quickjs_with_ctx(|ctx| { | ||
let callbacks: rquickjs::Object = ctx | ||
.clone() | ||
.globals() | ||
.get("_azleCallbacks") | ||
.map_err(|e| format!("Failed to get _azleCallbacks global: {}", e))?; | ||
|
||
let method_callback: rquickjs::Function = callbacks.get(&function_name)?; | ||
let method_callback: rquickjs::Function = callbacks | ||
.get(&function_name) | ||
.map_err(|e| format!("Failed to get method callback from _azleCallbacks: {}", e))?; | ||
|
||
let candid_args = if pass_arg_data { | ||
ic_cdk::api::call::arg_data_raw() | ||
} else { | ||
vec![] | ||
}; | ||
|
||
method_callback.call::<_, rquickjs::Undefined>((candid_args,))?; | ||
let promise: rquickjs::Promise = method_callback | ||
.call((candid_args,)) | ||
.map_err(|e| format!("Failed to execute method callback: {}", e))?; | ||
|
||
handle_promise_error(ctx.clone(), promise)?; | ||
|
||
Ok(()) | ||
}) { | ||
ic_cdk::trap(&format!("Azle MethodExecutionError: {}", error)); | ||
}); | ||
|
||
if let Err(e) = quickjs_result { | ||
ic_cdk::trap(&format!("Azle CanisterMethodError: {}", e)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.