Skip to content

Commit

Permalink
Merge pull request #2000 from demergent-labs/refactor_rust
Browse files Browse the repository at this point in the history
Refactor rust
  • Loading branch information
lastmjs authored Aug 20, 2024
2 parents 1965eef + 9cbafcb commit 0896540
Show file tree
Hide file tree
Showing 29 changed files with 501 additions and 528 deletions.
Binary file modified canister_templates/experimental.wasm
Binary file not shown.
Binary file modified canister_templates/stable.wasm
Binary file not shown.
14 changes: 6 additions & 8 deletions src/compiler/file_watcher/file_watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { ok } from '../utils/result';

type ActorReloadJs = ActorSubclass<_SERVICE>;
interface _SERVICE {
reload_js: ActorMethod<
[bigint, bigint, Uint8Array, bigint, number, boolean],
_azle_reload_js: ActorMethod<
[bigint, bigint, Uint8Array, bigint, number],
void
>;
}
Expand Down Expand Up @@ -100,13 +100,12 @@ async function reloadJs(
}

actor
.reload_js(
._azle_reload_js(
timestamp,
chunkNumber,
chunk,
BigInt(reloadedJs.length),
postUpgradeIndex,
experimental
postUpgradeIndex
)
.catch((error) => {
if (process.env.AZLE_VERBOSE === 'true') {
Expand All @@ -133,14 +132,13 @@ async function createActorReloadJs(
return Actor.createActor(
({ IDL }) => {
return IDL.Service({
reload_js: IDL.Func(
_azle_reload_js: IDL.Func(
[
IDL.Nat64,
IDL.Nat64,
IDL.Vec(IDL.Nat8),
IDL.Nat64,
IDL.Int32,
IDL.Bool
IDL.Int32
],
[],
[]
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/generate_wasm_binary.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { IOType } from 'child_process';

import { logGlobalDependencies } from './log_global_dependencies';
import { manipulateWasmBinary } from './manipulate_wasm_binary';
import { prepareRustStagingArea } from './prepare_rust_staging_area';
import { execSyncPretty } from './utils/exec_sync_pretty';
import {
EXPERIMENTAL_STATIC_CANISTER_TEMPLATE_PATH,
STABLE_STATIC_CANISTER_TEMPLATE_PATH
} from './utils/global_paths';
import { CanisterConfig, CompilerInfo } from './utils/types';
import { manipulateWasmBinary } from './wasm_binary_manipulation';

export async function generateWasmBinary(
canisterName: string,
Expand Down
8 changes: 1 addition & 7 deletions src/compiler/get_names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,7 @@ export async function getNames() {

const canisterId = getCanisterId(canisterName);

const reloadedJsPath = join(
'.azle',
canisterName,
'canister',
'src',
'main_reloaded.js'
);
const reloadedJsPath = join('.azle', canisterName, 'main_reloaded.js');

const esmAliases = canisterConfig.esm_aliases ?? {};
const esmExternals = canisterConfig.esm_externals ?? [];
Expand Down
43 changes: 43 additions & 0 deletions src/compiler/rust/canister/src/autoreload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::{cell::RefCell, collections::BTreeMap};

use crate::init_and_post_upgrade::initialize_js;

thread_local! {
static RELOADED_JS_TIMESTAMP: RefCell<u64> = RefCell::new(0);
static RELOADED_JS: RefCell<BTreeMap<u64, Vec<u8>>> = RefCell::new(BTreeMap::new());
}

pub fn reload_js(
timestamp: u64,
chunk_number: u64,
js_bytes: Vec<u8>,
total_len: u64,
function_index: i32,
) {
RELOADED_JS_TIMESTAMP.with(|reloaded_js_timestamp| {
let mut reloaded_js_timestamp_mut = reloaded_js_timestamp.borrow_mut();

if timestamp > *reloaded_js_timestamp_mut {
*reloaded_js_timestamp_mut = timestamp;

RELOADED_JS.with(|reloaded_js| {
let mut reloaded_js_mut = reloaded_js.borrow_mut();
reloaded_js_mut.clear();
});
}
});

RELOADED_JS.with(|reloaded_js| {
let mut reloaded_js_mut = reloaded_js.borrow_mut();
reloaded_js_mut.insert(chunk_number, js_bytes);

let reloaded_js_complete_bytes: Vec<u8> =
reloaded_js_mut.values().flat_map(|v| v.clone()).collect();

if reloaded_js_complete_bytes.len() as u64 == total_len {
let js_string = String::from_utf8_lossy(&reloaded_js_complete_bytes);
initialize_js(&js_string, false, function_index, 1, true); // TODO should the last arg be 0?
ic_cdk::println!("Azle: Reloaded canister JavaScript");
}
});
}
72 changes: 72 additions & 0 deletions src/compiler/rust/canister/src/candid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use wasmedge_quickjs::AsObject;

use crate::{ic, run_event_loop, wasm_binary_manipulation::get_js_code, RUNTIME};

// Heavily inspired by https://stackoverflow.com/a/47676844
#[no_mangle]
pub fn get_candid_pointer(experimental: i32) -> *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 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);
}));

RUNTIME.with(|_| {
let mut runtime = wasmedge_quickjs::Runtime::new();

runtime.run_with_context(|context| {
context.get_global().set(
"_azleWasmtimeCandidEnvironment",
wasmedge_quickjs::JsValue::Bool(true),
);

ic::register(context);

let js = get_js_code();

// TODO what do we do if there is an error in here?
context.eval_global_str("globalThis.exports = {};".to_string());
context.eval_global_str(format!(
"globalThis._azleExperimental = {};",
if experimental == 1 { "true" } else { "false" }
));
context.eval_module_str(std::str::from_utf8(&js).unwrap().to_string(), "azle_main");

run_event_loop(context);

let global = context.get_global();

let candid_info_function = global.get("candidInfoFunction").to_function().unwrap();

let candid_info = candid_info_function.call(&[]);

// TODO error handling is mostly done in JS right now
// TODO we would really like wasmedge-quickjs to add
// TODO good error info to JsException and move error handling
// TODO out of our own code
match &candid_info {
wasmedge_quickjs::JsValue::Exception(js_exception) => {
js_exception.dump_error();
panic!("TODO needs error info");
}
_ => run_event_loop(context),
};

let candid_info_string = candid_info.to_string().unwrap().to_string();

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

c_string.into_raw()
})
})
}
1 change: 1 addition & 0 deletions src/compiler/rust/canister/src/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[allow(unused)]
pub async fn chunk() {
let id = ic_cdk::id();
let method = "_azle_chunk";
Expand Down
50 changes: 50 additions & 0 deletions src/compiler/rust/canister/src/execute_method_js.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use wasmedge_quickjs::AsObject;

use crate::{run_event_loop, RUNTIME};

#[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 };

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 exports = global.get("exports");

let canister_methods = exports.get("canisterMethods").unwrap();

let callbacks = canister_methods.get("callbacks").unwrap();
let method_callback = callbacks.get(function_name).unwrap();

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

let candid_args_js_value: wasmedge_quickjs::JsValue =
context.new_array_buffer(&candid_args).into();

let method_callback_function = method_callback.to_function().unwrap();

let result = method_callback_function.call(&[candid_args_js_value]);

// TODO error handling is mostly done in JS right now
// TODO we would really like wasmedge-quickjs to add
// TODO good error info to JsException and move error handling
// TODO out of our own code
match &result {
wasmedge_quickjs::JsValue::Exception(js_exception) => {
js_exception.dump_error();
panic!("TODO needs error info");
}
_ => run_event_loop(context),
};
});
});
}
1 change: 1 addition & 0 deletions src/compiler/rust/canister/src/guards.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[allow(unused)]
pub fn guard_against_non_controllers() -> Result<(), String> {
if ic_cdk::api::is_controller(&ic_cdk::api::caller()) {
return Ok(());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::{AzleStableBTreeMapKey, STABLE_B_TREE_MAPS};
use crate::stable_b_tree_map::{AzleStableBTreeMapKey, STABLE_B_TREE_MAPS};

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/rust/canister/src/ic/stable_b_tree_map_get.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::{AzleStableBTreeMapKey, STABLE_B_TREE_MAPS};
use crate::stable_b_tree_map::{AzleStableBTreeMapKey, STABLE_B_TREE_MAPS};

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/rust/canister/src/ic/stable_b_tree_map_init.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use ic_stable_structures::{memory_manager::MemoryId, StableBTreeMap};
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::{MEMORY_MANAGER_REF_CELL, STABLE_B_TREE_MAPS};
use crate::stable_b_tree_map::STABLE_B_TREE_MAPS;
use crate::MEMORY_MANAGER_REF_CELL;

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::{AzleStableBTreeMapKey, AzleStableBTreeMapValue, STABLE_B_TREE_MAPS};
use crate::stable_b_tree_map::{
AzleStableBTreeMapKey, AzleStableBTreeMapValue, STABLE_B_TREE_MAPS,
};

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::STABLE_B_TREE_MAPS;
use crate::stable_b_tree_map::STABLE_B_TREE_MAPS;

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::convert::TryInto;

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

use crate::STABLE_B_TREE_MAPS;
use crate::stable_b_tree_map::STABLE_B_TREE_MAPS;

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::convert::TryInto;

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

use crate::STABLE_B_TREE_MAPS;
use crate::stable_b_tree_map::STABLE_B_TREE_MAPS;

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/rust/canister/src/ic/stable_b_tree_map_len.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::STABLE_B_TREE_MAPS;
use crate::stable_b_tree_map::STABLE_B_TREE_MAPS;

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use wasmedge_quickjs::{Context, JsFn, JsValue};

use crate::{AzleStableBTreeMapKey, STABLE_B_TREE_MAPS};
use crate::stable_b_tree_map::{AzleStableBTreeMapKey, STABLE_B_TREE_MAPS};

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::convert::TryInto;

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

use crate::STABLE_B_TREE_MAPS;
use crate::stable_b_tree_map::STABLE_B_TREE_MAPS;

pub struct NativeFunction;
impl JsFn for NativeFunction {
Expand Down
Loading

0 comments on commit 0896540

Please sign in to comment.