Skip to content

Commit

Permalink
call_raw and call_raw128 implemented!
Browse files Browse the repository at this point in the history
  • Loading branch information
lastmjs committed Jan 17, 2024
1 parent 74480bd commit dbd3983
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 191 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion src/compiler/rust/canister/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ ic-cdk-macros = "0.7.0"
ic-wasi-polyfill = { git = "https://github.com/wasm-forge/ic-wasi-polyfill", rev = "1693665ed57adc4f997a0313555ec0b0b5de1c07", features = [
"transient",
] }
wasmedge_quickjs = { git = "https://github.com/demergent-labs/wasmedge-quickjs", rev = "09edab8fbfa15e17f91d834003589fc7e60357ba" }
wasmedge_quickjs = { git = "https://github.com/demergent-labs/wasmedge-quickjs", rev = "218238f970b2d1c3e34d712c6be9f558b8364716" }
# wasmedge_quickjs = { path = "/home/wasmedge-quickjs" }
183 changes: 100 additions & 83 deletions src/compiler/rust/canister/src/ic/call_raw.rs
Original file line number Diff line number Diff line change
@@ -1,89 +1,106 @@
// TODO basically copied into call_raw128
use std::convert::TryInto;

use quickjs_wasm_rs::{to_qjs_value, CallbackArg, JSContextRef, JSValue, JSValueRef};

use crate::CONTEXT;

pub fn native_function<'a>(
context: &'a JSContextRef,
_this: &CallbackArg,
args: &[CallbackArg],
) -> Result<JSValueRef<'a>, anyhow::Error> {
let promise_id: String = args
.get(0)
.expect("call_raw promise_id argument is undefined")
.to_js_value()?
.try_into()?;
let canister_id_bytes: Vec<u8> = args
.get(1)
.expect("call_raw canister_id_bytes is undefined")
.to_js_value()?
.try_into()?;
let canister_id = candid::Principal::from_slice(&canister_id_bytes);
let method: String = args
.get(2)
.expect("call_raw method argument is undefined")
.to_js_value()?
.try_into()?;
let args_raw: Vec<u8> = args
.get(3)
.expect("call_raw args_raw argument is undefined")
.to_js_value()?
.try_into()?;
let payment_candid_bytes: Vec<u8> = args
.get(4)
.expect("call_raw payment_candid_bytes argument is undefined")
.to_js_value()?
.try_into()?;
let payment: u64 = candid::decode_one(&payment_candid_bytes)?;

ic_cdk::spawn(async move {
let call_result =
ic_cdk::api::call::call_raw(canister_id, &method, &args_raw, payment).await;

let (should_resolve, js_value) = match call_result {
Ok(candid_bytes) => {
let candid_bytes_js_value: JSValue = candid_bytes.into();
(true, candid_bytes_js_value)
}
Err(err) => {
let err_js_value: JSValue = format!(
"Rejection code {rejection_code}, {error_message}",
rejection_code = (err.0 as i32).to_string(),
error_message = err.1
)
.into();

(false, err_js_value)
}

use wasmedge_quickjs::{AsObject, Context, JsFn, JsValue};

use crate::RUNTIME;

pub struct NativeFunction;
impl JsFn for NativeFunction {
fn call(context: &mut Context, this_val: JsValue, argv: &[JsValue]) -> JsValue {
let promise_id = if let JsValue::String(js_string) = argv.get(0).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};

let canister_id_bytes = if let JsValue::ArrayBuffer(js_array_buffer) = argv.get(1).unwrap()
{
js_array_buffer.to_vec()
} else {
panic!("conversion from JsValue to JsArrayBuffer failed")
};
let canister_id = candid::Principal::from_slice(&canister_id_bytes);

let method = if let JsValue::String(js_string) = argv.get(2).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};

let args_raw = if let JsValue::ArrayBuffer(js_array_buffer) = argv.get(3).unwrap() {
js_array_buffer.to_vec()
} else {
panic!("conversion from JsValue to JsArrayBuffer failed")
};

let payment_string = if let JsValue::String(js_string) = argv.get(4).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};
let payment: u64 = payment_string.parse().unwrap();

ic_cdk::spawn(async move {
let call_result =
ic_cdk::api::call::call_raw(canister_id, &method, &args_raw, payment).await;

RUNTIME.with(|runtime| {
let mut runtime = runtime.borrow_mut();
let runtime = runtime.as_mut().unwrap();

runtime.run_with_context(|context| {
let global = context.get_global();

let (should_resolve, js_value) = match &call_result {
Ok(candid_bytes) => {
let candid_bytes_js_value: JsValue =
context.new_array_buffer(candid_bytes).into();

(true, candid_bytes_js_value)
}
Err(err) => {
let err_js_value: JsValue = context
.new_error(&format!(
"Rejection code {rejection_code}, {error_message}",
rejection_code = (err.0 as i32).to_string(),
error_message = err.1
))
.into();

(false, err_js_value)
}
};

if should_resolve {
let resolve = global
.get("_azleResolveIds")
.to_obj()
.unwrap()
.get(format!("_resolve_{promise_id}").as_str())
.to_function()
.unwrap();

resolve.call(&[js_value.clone()]);
} else {
let reject = global
.get("_azleRejectIds")
.to_obj()
.unwrap()
.get(format!("_reject_{promise_id}").as_str())
.to_function()
.unwrap();

reject.call(&[js_value.clone()]);
}

CONTEXT.with(|context| {
let mut context = context.borrow_mut();
let context = context.as_mut().unwrap();

let global = context.global_object().unwrap();

let js_value_ref = to_qjs_value(&context, &js_value).unwrap();

if should_resolve {
let resolve = global
.get_property("_azleResolveIds").unwrap()
.get_property(format!("_resolve_{promise_id}").as_str())
.unwrap();
resolve.call(&resolve, &[js_value_ref]).unwrap();
} else {
let reject = global
.get_property("_azleRejectIds").unwrap()
.get_property(format!("_reject_{promise_id}").as_str())
.unwrap();
reject.call(&reject, &[js_value_ref]).unwrap();
}

context.execute_pending().unwrap();
// TODO do we need to progress setTimeouts and stuff?
// TODO make sure to test this
// context.event_loop().unwrap().run_tick_task();
context.promise_loop_poll();
});
});
});
});

context.undefined_value()
JsValue::UnDefined
}
}
183 changes: 100 additions & 83 deletions src/compiler/rust/canister/src/ic/call_raw128.rs
Original file line number Diff line number Diff line change
@@ -1,89 +1,106 @@
// TODO basically copied from call_raw
use std::convert::TryInto;

use quickjs_wasm_rs::{to_qjs_value, CallbackArg, JSContextRef, JSValue, JSValueRef};

use crate::CONTEXT;

pub fn native_function<'a>(
context: &'a JSContextRef,
_this: &CallbackArg,
args: &[CallbackArg],
) -> Result<JSValueRef<'a>, anyhow::Error> {
let promise_id: String = args
.get(0)
.expect("call_raw promise_id argument is undefined")
.to_js_value()?
.try_into()?;
let canister_id_bytes: Vec<u8> = args
.get(1)
.expect("call_raw canister_id_bytes is undefined")
.to_js_value()?
.try_into()?;
let canister_id = candid::Principal::from_slice(&canister_id_bytes);
let method: String = args
.get(2)
.expect("call_raw method argument is undefined")
.to_js_value()?
.try_into()?;
let args_raw: Vec<u8> = args
.get(3)
.expect("call_raw args_raw argument is undefined")
.to_js_value()?
.try_into()?;
let payment_candid_bytes: Vec<u8> = args
.get(4)
.expect("call_raw payment_candid_bytes argument is undefined")
.to_js_value()?
.try_into()?;
let payment: u128 = candid::decode_one(&payment_candid_bytes)?;

ic_cdk::spawn(async move {
let call_result =
ic_cdk::api::call::call_raw128(canister_id, &method, &args_raw, payment).await;

let (should_resolve, js_value) = match call_result {
Ok(candid_bytes) => {
let candid_bytes_js_value: JSValue = candid_bytes.into();
(true, candid_bytes_js_value)
}
Err(err) => {
let err_js_value: JSValue = format!(
"Rejection code {rejection_code}, {error_message}",
rejection_code = (err.0 as i32).to_string(),
error_message = err.1
)
.into();

(false, err_js_value)
}

use wasmedge_quickjs::{AsObject, Context, JsFn, JsValue};

use crate::RUNTIME;

pub struct NativeFunction;
impl JsFn for NativeFunction {
fn call(context: &mut Context, this_val: JsValue, argv: &[JsValue]) -> JsValue {
let promise_id = if let JsValue::String(js_string) = argv.get(0).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};

let canister_id_bytes = if let JsValue::ArrayBuffer(js_array_buffer) = argv.get(1).unwrap()
{
js_array_buffer.to_vec()
} else {
panic!("conversion from JsValue to JsArrayBuffer failed")
};
let canister_id = candid::Principal::from_slice(&canister_id_bytes);

let method = if let JsValue::String(js_string) = argv.get(2).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};

let args_raw = if let JsValue::ArrayBuffer(js_array_buffer) = argv.get(3).unwrap() {
js_array_buffer.to_vec()
} else {
panic!("conversion from JsValue to JsArrayBuffer failed")
};

let payment_string = if let JsValue::String(js_string) = argv.get(4).unwrap() {
js_string.to_string()
} else {
panic!("conversion from JsValue to JsString failed")
};
let payment: u128 = payment_string.parse().unwrap();

ic_cdk::spawn(async move {
let call_result =
ic_cdk::api::call::call_raw128(canister_id, &method, &args_raw, payment).await;

RUNTIME.with(|runtime| {
let mut runtime = runtime.borrow_mut();
let runtime = runtime.as_mut().unwrap();

runtime.run_with_context(|context| {
let global = context.get_global();

let (should_resolve, js_value) = match &call_result {
Ok(candid_bytes) => {
let candid_bytes_js_value: JsValue =
context.new_array_buffer(candid_bytes).into();

(true, candid_bytes_js_value)
}
Err(err) => {
let err_js_value: JsValue = context
.new_error(&format!(
"Rejection code {rejection_code}, {error_message}",
rejection_code = (err.0 as i32).to_string(),
error_message = err.1
))
.into();

(false, err_js_value)
}
};

if should_resolve {
let resolve = global
.get("_azleResolveIds")
.to_obj()
.unwrap()
.get(format!("_resolve_{promise_id}").as_str())
.to_function()
.unwrap();

resolve.call(&[js_value.clone()]);
} else {
let reject = global
.get("_azleRejectIds")
.to_obj()
.unwrap()
.get(format!("_reject_{promise_id}").as_str())
.to_function()
.unwrap();

reject.call(&[js_value.clone()]);
}

CONTEXT.with(|context| {
let mut context = context.borrow_mut();
let context = context.as_mut().unwrap();

let global = context.global_object().unwrap();

let js_value_ref = to_qjs_value(&context, &js_value).unwrap();

if should_resolve {
let resolve = global
.get_property("_azleResolveIds").unwrap()
.get_property(format!("_resolve_{promise_id}").as_str())
.unwrap();
resolve.call(&resolve, &[js_value_ref]).unwrap();
} else {
let reject = global
.get_property("_azleRejectIds").unwrap()
.get_property(format!("_reject_{promise_id}").as_str())
.unwrap();
reject.call(&reject, &[js_value_ref]).unwrap();
}

context.execute_pending().unwrap();
// TODO do we need to progress setTimeouts and stuff?
// TODO make sure to test this
// context.event_loop().unwrap().run_tick_task();
context.promise_loop_poll();
});
});
});
});

context.undefined_value()
JsValue::UnDefined
}
}
Loading

0 comments on commit dbd3983

Please sign in to comment.