Skip to content

Commit

Permalink
update all types
Browse files Browse the repository at this point in the history
  • Loading branch information
lastmjs committed Jan 2, 2025
1 parent ffffa68 commit b41aa4b
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 94 deletions.
Binary file modified canister_templates/experimental.wasm
Binary file not shown.
Binary file modified canister_templates/stable.wasm
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ pub extern "C" fn execute_method_js(function_index: i32, pass_arg_data: i32) {
runtime.run_with_context(|context| {
let global = context.get_global();

let canister_class_instance = global.get("_azleCanisterClassInstance");
let exported_canister_class_instance = global.get("_azleExportedCanisterClassInstance");

let callbacks = if matches!(canister_class_instance, JsValue::UnDefined) {
let callbacks = if matches!(exported_canister_class_instance, JsValue::UnDefined) {
global.get("_azleCallbacks")
} else {
canister_class_instance.get("_azleCallbacks").unwrap()
exported_canister_class_instance
.get("_azleCallbacks")
.unwrap()
};

let method_callback = callbacks.get(&function_name).unwrap();
Expand Down
12 changes: 6 additions & 6 deletions src/build/stable/commands/compile/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ function getPrelude(main: string): string {

export function handleClassApiCanister(): string {
return /*TS*/ `
const canisterClassInstance = new Canister.default();
globalThis._azleCanisterClassInstance = canisterClassInstance;
const exportedCanisterClassInstance = new Canister.default();
globalThis._azleExportedCanisterClassInstance = exportedCanisterClassInstance;
const canisterIdlType = IDL.Service(canisterClassInstance._azleCanisterMethodIdlTypes);
const canisterIdlType = IDL.Service(exportedCanisterClassInstance._azleCanisterMethodIdlTypes);
const candid = canisterIdlType.accept(new DidVisitor(), {
...getDefaultVisitorData(),
isFirstService: true,
systemFuncs: canisterClassInstance._azleInitAndPostUpgradeIdlTypes
systemFuncs: exportedCanisterClassInstance._azleInitAndPostUpgradeIdlTypes
});
globalThis._azleGetCandidAndMethodMeta = () => {
return JSON.stringify({
candid: toDidString(candid),
methodMeta: canisterClassInstance._azleMethodMeta
methodMeta: exportedCanisterClassInstance._azleMethodMeta
});
};
`;
Expand Down Expand Up @@ -111,7 +111,7 @@ function experimentalMessage(importName: string): string {
function handleBenchmarking(): string {
return /*TS*/ `
if (globalThis._azleRecordBenchmarks === true) {
const methodMeta = canisterClassInstance._azleMethodMeta;
const methodMeta = exportedCanisterClassInstance._azleMethodMeta;
globalThis._azleCanisterMethodNames = Object.entries(methodMeta).reduce((acc, [key, value]) => {
if (value === undefined) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,24 @@ fn execute_method_js_with_result(
pass_arg_data: bool,
) -> Result<(), Box<dyn Error>> {
quickjs_with_ctx(|ctx| {
let canister_class_instance: Object = ctx
let exported_canister_class_instance: Object = ctx
.clone()
.globals()
.get("_azleCanisterClassInstance")
.map_err(|e| format!("Failed to get globalThis._azleCanisterClassInstance: {e}"))?;
.get("_azleExportedCanisterClassInstance")
.map_err(|e| {
format!("Failed to get globalThis._azleExportedCanisterClassInstance: {e}")
})?;

let callbacks: Object = canister_class_instance
let callbacks: Object = exported_canister_class_instance
.get("_azleCallbacks")
.map_err(|e| format!("Failed to get canisterClassInstance._azleCallbacks: {e}"))?;
.map_err(|e| {
format!("Failed to get exportedCanisterClassInstance._azleCallbacks: {e}")
})?;

let method_callback: Function = callbacks.get(&function_name).map_err(|e| {
format!("Failed to get canisterClassInstance._azleCallbacks[{function_name}]: {e}")
format!(
"Failed to get exportedCanisterClassInstance._azleCallbacks[{function_name}]: {e}"
)
})?;

let candid_args = if pass_arg_data {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/stable/canister_methods/heartbeat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { decoratorArgumentsHandler, MethodType } from '.';

export function heartbeat<This, Args extends any[], Return>(
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext
context: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
): void {
decoratorArgumentsHandler('heartbeat', originalMethod, context);
}
117 changes: 71 additions & 46 deletions src/lib/stable/canister_methods/index.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
import { IDL } from '@dfinity/candid';

import { MethodMeta } from '../../../build/stable/utils/types';
import { handleUncaughtError } from '../error';
import {
CanisterMethodMode,
executeAndReplyWithCandidSerde
} from '../execute_with_candid_serde';

export interface ExportedCanisterClass {
_azleCallbacks?: {
[key: string]: MethodType<ExportedCanisterClass, any[], any>;
};
_azleCanisterMethodIdlTypes?: { [key: string]: IDL.FuncClass };
_azleCanisterMethodsIndex?: number;
_azleInitAndPostUpgradeIdlTypes?: IDL.FuncClass[];
_azleMethodMeta?: MethodMeta;
}

export type MethodType<This, Args extends any[], Return> = (
this: This,
...args: Args
) => Return;

export type DecoratorFunction<This, Args extends any[], Return> = (
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext
context: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
) => MethodType<This, Args, Return>;

export function decoratorArgumentsHandler<This, Args extends any[], Return>(
canisterMethodMode: CanisterMethodMode,
param1?: MethodType<This, Args, Return> | IDL.Type[],
param2?: ClassMethodDecoratorContext | IDL.Type,
param2?:
| ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
| IDL.Type,
param3?: { composite?: boolean; manual?: boolean }
): MethodType<This, Args, Return> | DecoratorFunction<This, Args, Return> {
const decoratorIsOverloadWithoutParams = isDecoratorOverloadWithoutParams(
param1,
param2
);

if (decoratorIsOverloadWithoutParams === true) {
const originalMethod = param1 as MethodType<This, Args, Return>;
const context = param2 as ClassMethodDecoratorContext;
):
| MethodType<ExportedCanisterClass, Args, Return>
| DecoratorFunction<ExportedCanisterClass, Args, Return> {
const decoratorIsOverloadedWithoutParams =
isDecoratorOverloadedWithoutParams(param1, param2);

if (decoratorIsOverloadedWithoutParams === true) {
const originalMethod = param1 as MethodType<
ExportedCanisterClass,
Args,
Return
>;
const context = param2 as ClassMethodDecoratorContext<
ExportedCanisterClass,
MethodType<ExportedCanisterClass, Args, Return>
>;

return decoratorImplementation(
canisterMethodMode,
Expand All @@ -42,9 +62,12 @@ export function decoratorArgumentsHandler<This, Args extends any[], Return>(
const options = param3;

return (
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext
): MethodType<This, Args, Return> => {
originalMethod: MethodType<ExportedCanisterClass, Args, Return>,
context: ClassMethodDecoratorContext<
ExportedCanisterClass,
MethodType<ExportedCanisterClass, Args, Return>
>
): MethodType<ExportedCanisterClass, Args, Return> => {
return decoratorImplementation(
canisterMethodMode,
originalMethod,
Expand All @@ -57,9 +80,11 @@ export function decoratorArgumentsHandler<This, Args extends any[], Return>(
}
}

function isDecoratorOverloadWithoutParams<This, Args extends any[], Return>(
function isDecoratorOverloadedWithoutParams<This, Args extends any[], Return>(
param1?: MethodType<This, Args, Return> | IDL.Type[],
param2?: ClassMethodDecoratorContext | IDL.Type
param2?:
| ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
| IDL.Type
): boolean {
return (
typeof param1 === 'function' &&
Expand All @@ -71,124 +96,124 @@ function isDecoratorOverloadWithoutParams<This, Args extends any[], Return>(
);
}

function decoratorImplementation<This, Args extends any[], Return>(
function decoratorImplementation<
This extends ExportedCanisterClass,
Args extends any[],
Return
>(
canisterMethodMode: CanisterMethodMode,
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext,
context: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>,
paramIdlTypes?: IDL.Type[],
returnIdlType?: IDL.Type,
options?: { composite?: boolean; manual?: boolean }
): MethodType<This, Args, Return> {
context.addInitializer(function () {
let canisterClassInstance = this as any;

if (canisterClassInstance._azleCanisterMethodsIndex === undefined) {
canisterClassInstance._azleCanisterMethodsIndex = 0;
if (this._azleCanisterMethodsIndex === undefined) {
this._azleCanisterMethodsIndex = 0;
}

if (canisterClassInstance._azleCanisterMethodIdlTypes === undefined) {
canisterClassInstance._azleCanisterMethodIdlTypes = {};
if (this._azleCanisterMethodIdlTypes === undefined) {
this._azleCanisterMethodIdlTypes = {};
}

if (
canisterClassInstance._azleInitAndPostUpgradeIdlTypes === undefined
) {
canisterClassInstance._azleInitAndPostUpgradeIdlTypes = [];
if (this._azleInitAndPostUpgradeIdlTypes === undefined) {
this._azleInitAndPostUpgradeIdlTypes = [];
}

if (canisterClassInstance._azleMethodMeta === undefined) {
canisterClassInstance._azleMethodMeta = {
if (this._azleMethodMeta === undefined) {
this._azleMethodMeta = {
queries: [],
updates: []
};
}

if (canisterClassInstance._azleCallbacks === undefined) {
canisterClassInstance._azleCallbacks = {};
if (this._azleCallbacks === undefined) {
this._azleCallbacks = {};
}

const name = context.name as string;

const index = canisterClassInstance._azleCanisterMethodsIndex++;
const index = this._azleCanisterMethodsIndex++;
const indexString = index.toString();

if (canisterMethodMode === 'query') {
canisterClassInstance._azleMethodMeta.queries?.push({
this._azleMethodMeta.queries?.push({
name,
index,
composite: options?.composite ?? false
});

canisterClassInstance._azleCanisterMethodIdlTypes[name] = IDL.Func(
this._azleCanisterMethodIdlTypes[name] = IDL.Func(
paramIdlTypes ?? [],
returnIdlType === undefined ? [] : [returnIdlType],
['query']
);
}

if (canisterMethodMode === 'update') {
canisterClassInstance._azleMethodMeta.updates?.push({
this._azleMethodMeta.updates?.push({
name,
index
});

canisterClassInstance._azleCanisterMethodIdlTypes[name] = IDL.Func(
this._azleCanisterMethodIdlTypes[name] = IDL.Func(
paramIdlTypes ?? [],
returnIdlType === undefined ? [] : [returnIdlType]
);
}

if (canisterMethodMode === 'init') {
canisterClassInstance._azleMethodMeta.init = {
this._azleMethodMeta.init = {
name,
index
};

canisterClassInstance._azleInitAndPostUpgradeIdlTypes.push(
this._azleInitAndPostUpgradeIdlTypes.push(
IDL.Func(paramIdlTypes ?? [], [], ['init'])
);
}

if (canisterMethodMode === 'postUpgrade') {
canisterClassInstance._azleMethodMeta.post_upgrade = {
this._azleMethodMeta.post_upgrade = {
name,
index
};

canisterClassInstance._azleInitAndPostUpgradeIdlTypes.push(
this._azleInitAndPostUpgradeIdlTypes.push(
IDL.Func(paramIdlTypes ?? [], [], ['post_upgrade'])
);
}

if (canisterMethodMode === 'preUpgrade') {
canisterClassInstance._azleMethodMeta.pre_upgrade = {
this._azleMethodMeta.pre_upgrade = {
name,
index
};
}

if (canisterMethodMode === 'heartbeat') {
canisterClassInstance._azleMethodMeta.heartbeat = {
this._azleMethodMeta.heartbeat = {
name,
index
};
}

if (canisterMethodMode === 'inspectMessage') {
canisterClassInstance._azleMethodMeta.inspect_message = {
this._azleMethodMeta.inspect_message = {
name,
index
};
}

canisterClassInstance._azleCallbacks[indexString] = async (
this._azleCallbacks[indexString] = async (
args?: Uint8Array
): Promise<void> => {
try {
await executeAndReplyWithCandidSerde(
canisterMethodMode,
args ?? new Uint8Array(),
originalMethod.bind(canisterClassInstance),
originalMethod.bind(this), // TODO manually test context and ensure we have automatic tests for this
paramIdlTypes ?? [],
returnIdlType,
options?.manual ?? false
Expand Down
21 changes: 14 additions & 7 deletions src/lib/stable/canister_methods/init.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { IDL } from '@dfinity/candid';

import { decoratorArgumentsHandler, DecoratorFunction, MethodType } from '.';
import {
decoratorArgumentsHandler,
DecoratorFunction,
ExportedCanisterClass,
MethodType
} from '.';

export function init<This, Args extends any[], Return>(
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext
): MethodType<This, Args, Return>;
context: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
): MethodType<ExportedCanisterClass, Args, Return>;

export function init<This, Args extends any[], Return>(
paramIdlTypes?: IDL.Type[]
): (
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext
) => MethodType<This, Args, Return>;
context: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
) => MethodType<ExportedCanisterClass, Args, Return>;

export function init<This, Args extends any[], Return>(
param1?: MethodType<This, Args, Return> | IDL.Type[],
param2?: ClassMethodDecoratorContext
): MethodType<This, Args, Return> | DecoratorFunction<This, Args, Return> {
param2?: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
):
| MethodType<ExportedCanisterClass, Args, Return>
| DecoratorFunction<ExportedCanisterClass, Args, Return> {
return decoratorArgumentsHandler('init', param1, param2);
}
2 changes: 1 addition & 1 deletion src/lib/stable/canister_methods/inspect_message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { decoratorArgumentsHandler, MethodType } from '.';
// TODO explain here in a jsdoc that the dev can get the raw args using argDataRaw
export function inspectMessage<This, Args extends any[], Return>(
originalMethod: MethodType<This, Args, Return>,
context: ClassMethodDecoratorContext
context: ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>
): void {
decoratorArgumentsHandler('inspectMessage', originalMethod, context);
}
Loading

0 comments on commit b41aa4b

Please sign in to comment.