Skip to content

Commit

Permalink
some initial error structure is in place
Browse files Browse the repository at this point in the history
  • Loading branch information
lastmjs committed Oct 21, 2024
1 parent 7960255 commit f07de25
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 205 deletions.
Binary file modified canister_templates/stable.wasm
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#[derive(Debug)]
pub enum AzleError {
Init(Box<dyn std::error::Error>),
PostUpgrade(Box<dyn std::error::Error>),
MethodExecution(Box<dyn std::error::Error>),
QuickJSContextNotInitialized,
QuickJSCallbackExecutionFailed(Box<dyn std::error::Error>),
WasmDataVecToString(Box<dyn std::error::Error>),
WasmDataStringToStruct(Box<dyn std::error::Error>),
}

impl std::fmt::Display for AzleError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AzleError::QuickJSContextNotInitialized => {
write!(f, "QuickJS context not initialized")
}
AzleError::QuickJSCallbackExecutionFailed(error) => {
write!(f, "QuickJS callback execution failed: {}", error)
}
AzleError::MethodExecution(error) => {
write!(f, "Azle MethodExecutionError: {}", error)
}
AzleError::Init(error) => write!(f, "Azle InitError: {}", error),
AzleError::PostUpgrade(error) => write!(f, "Azle PostUpgradeError: {}", error),
AzleError::WasmDataVecToString(error) => {
write!(
f,
"WasmData conversion failed while converting Vec<u8> to String: {}",
error
)
}
AzleError::WasmDataStringToStruct(error) => {
write!(
f,
"WasmData conversion failed while converting String to WasmData Struct: {}",
error
)
}
}
}
}

impl std::error::Error for AzleError {}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
use crate::{
ic, quickjs_with_ctx, wasm_binary_manipulation::get_js_code, CONTEXT_REF_CELL, MODULE_NAME,
};
use std::error::Error;

// TODO we might not need any of these panic hooks

// Heavily inspired by https://stackoverflow.com/a/47676844
#[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 = match panic_info.payload().downcast_ref::<&str>() {
Some(s) => *s,
None => "Unknown panic message",
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 {
Expand All @@ -23,44 +25,46 @@ pub fn get_candid_and_method_meta_pointer() -> *mut std::os::raw::c_char {
ic_cdk::println!("{}", message);
}));

let runtime = rquickjs::Runtime::new().unwrap();
let context = rquickjs::Context::full(&runtime).unwrap();
match initialize_and_get_candid() {
Ok(c_string) => c_string,
Err(e) => {
ic_cdk::trap(&format!("Error during candid initialization: {}", e));
}
}
}

fn initialize_and_get_candid() -> Result<*mut std::os::raw::c_char, 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| {
quickjs_with_ctx(|ctx| -> Result<*mut std::os::raw::c_char, Box<dyn Error>> {
ctx.clone()
.globals()
.set("_azleNodeWasmEnvironment", true)
.unwrap();
.set("_azleNodeWasmEnvironment", true)?;

ic::register(ctx.clone());
ic::register(ctx.clone())?;

ctx.clone()
.globals()
.set("exports", rquickjs::Object::new(ctx.clone()).unwrap())
.unwrap();
.set("exports", rquickjs::Object::new(ctx.clone())?)?;

ctx.clone()
.globals()
.set("_azleExperimental", false)
.unwrap();
ctx.clone().globals().set("_azleExperimental", false)?;

let js = get_js_code();
let js = get_js_code()?;

// TODO is there a better name for this main module?
// TODO this returns a promise...make sure we handle it appropriately
rquickjs::Module::evaluate(ctx.clone(), MODULE_NAME, js).unwrap();
rquickjs::Module::evaluate(ctx.clone(), MODULE_NAME, std::str::from_utf8(&js)?)?;

let get_candid_and_method_meta: rquickjs::Function =
ctx.globals().get("_azleGetCandidAndMethodMeta").unwrap();
ctx.globals().get("_azleGetCandidAndMethodMeta")?;

let candid_and_method_meta: String = get_candid_and_method_meta.call(()).unwrap();
let candid_and_method_meta: String = get_candid_and_method_meta.call(())?;

let c_string = std::ffi::CString::new(candid_and_method_meta).unwrap();
let c_string = std::ffi::CString::new(candid_and_method_meta)?;

c_string.into_raw()
Ok(c_string.into_raw())
})
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
use crate::quickjs_with_ctx;
use std::error::Error;

#[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 = if pass_arg_data == 1 { true } else { false };
let function_name = function_index.to_string();
let pass_arg_data = pass_arg_data == 1;

quickjs_with_ctx(|ctx| {
let callbacks: rquickjs::Object = ctx.clone().globals().get("_azleCallbacks").unwrap();
if let Err(error) = quickjs_with_ctx(|ctx| -> Result<(), Box<dyn Error>> {
let callbacks: rquickjs::Object = ctx.clone().globals().get("_azleCallbacks")?;

let method_callback: rquickjs::Function = callbacks.get(function_name).unwrap();
let method_callback: rquickjs::Function = callbacks.get(&function_name)?;

let candid_args = if pass_arg_data {
ic_cdk::api::call::arg_data_raw()
} else {
vec![]
};

method_callback
.call::<_, rquickjs::Undefined>((candid_args,))
.unwrap();
});
method_callback.call::<_, rquickjs::Undefined>((candid_args,))?;

Ok(())
}) {
ic_cdk::trap(&format!("Azle MethodExecutionError: {}", error));
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use rquickjs::{Ctx, Function};

pub fn get_function(context: Ctx) -> Function {
pub fn get_function(context: Ctx) -> Result<Function, rquickjs::Error> {
Function::new(context, || {
ic_cdk::api::call::accept_message();
})
.unwrap()
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use rquickjs::{Ctx, Function, TypedArray};

pub fn get_function(context: Ctx) -> Function {
pub fn get_function(context: Ctx) -> Result<Function, rquickjs::Error> {
Function::new(context.clone(), move || {
TypedArray::<u8>::new(context.clone(), ic_cdk::api::call::arg_data_raw())
})
.unwrap()
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub fn get_function(ctx: Ctx) -> Function {

quickjs_with_ctx(move |ctx| {
resolve_or_reject(ctx.clone(), &call_result, &promise_id);

Ok(())
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use rquickjs::{Ctx, Function, TypedArray};
use rquickjs::{Ctx, Function, Result, TypedArray};

pub fn get_function(context: Ctx) -> Function {
pub fn get_function(context: Ctx) -> Result<Function> {
Function::new(context.clone(), move || {
TypedArray::<u8>::new(context.clone(), ic_cdk::api::caller().as_slice())
})
.unwrap()
}
Loading

0 comments on commit f07de25

Please sign in to comment.