Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor js rearchitecture code #1373

Merged
merged 36 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9dfdaf5
rename call_raw entry file to index
bdemann Oct 7, 2023
33a30d8
make visitVariant more declarative
bdemann Oct 12, 2023
ef0905f
unify encode and encodeMultiple, for decode also
bdemann Oct 12, 2023
aa80bf0
import clean up
bdemann Oct 17, 2023
723fa9c
remove unecessary parent parameters
bdemann Oct 17, 2023
8adae3e
idiot proof the default visitor data
bdemann Oct 17, 2023
71ed079
break service into parts
bdemann Oct 17, 2023
c00ab7a
make service more declarative
bdemann Oct 17, 2023
4e0c1bb
rename toIdl
bdemann Oct 17, 2023
91ff2f6
uniformize capitalization of IDL in function names
bdemann Oct 17, 2023
142ed96
clean up globals
bdemann Oct 17, 2023
9d57375
remove unecessary import
bdemann Oct 17, 2023
fd84f8e
pull out visitService to it's own file
bdemann Oct 18, 2023
6aef0dd
clean up visit_service
bdemann Oct 18, 2023
69f9311
move each visit method to it's own file
bdemann Oct 18, 2023
53d5917
clean up executeMethod
bdemann Oct 18, 2023
bdc8859
fix error with visit_service
bdemann Oct 18, 2023
5538f6d
update _azleIc type to be possibly undefined
bdemann Oct 18, 2023
189889d
rename properties to not have _azle where possible
bdemann Oct 18, 2023
eb65851
rename _kind to _azleKind
bdemann Oct 18, 2023
5174e75
rename to lowercase
bdemann Oct 18, 2023
57dfe27
pr fixes
bdemann Oct 18, 2023
0da99cc
remove cross canister callback stuff
bdemann Oct 18, 2023
0d4357d
rename toJSON so it doesn't conflict with standard toJSON
bdemann Oct 18, 2023
8afb46a
move things into their own files
bdemann Oct 18, 2023
a3213a4
move everything into it's own file
bdemann Oct 18, 2023
b3888a7
fix imports
bdemann Oct 18, 2023
23004e0
unify toParamIdl and toReturnIdl
bdemann Oct 18, 2023
f67057d
fix imports
bdemann Oct 18, 2023
86509a6
clean up bigint casting
bdemann Oct 18, 2023
75f12f8
fix heartbeat
bdemann Oct 18, 2023
08eccf4
pr fixes
bdemann Oct 18, 2023
2b85bd3
pr fixes
bdemann Oct 18, 2023
a5a9640
fix type error
bdemann Oct 18, 2023
e3cc787
update imports to be direct
bdemann Oct 18, 2023
27fb3e2
organize encode/decode visitors
bdemann Oct 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/call_raw/dfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"canisters": {
"call_raw": {
"type": "custom",
"main": "src/call_raw.ts",
"candid": "src/call_raw.did",
"main": "src/index.ts",
"build": "npx azle call_raw",
"candid": "src/index.did",
"wasm": ".azle/call_raw/call_raw.wasm",
"gzip": true,
"declarations": {
Expand Down
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions examples/date/src/index.did
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ service: () -> {
getUtcMinutes: (text) -> (nat32) query;
getUtcMonth: (text) -> (nat32) query;
getUtcSeconds: (text) -> (nat32) query;
now: () -> (nat64) query;
parse: (text) -> (nat64) query;
setDate: (text, nat32) -> (nat32) query;
setFullYear: (text, nat32) -> (nat32) query;
setHours: (text, nat32) -> (nat32) query;
Expand All @@ -34,11 +36,9 @@ service: () -> {
setUtcSeconds: (text, nat32) -> (nat32) query;
toDateString: (text) -> (text) query;
toISOString: (text) -> (text) query;
toJSON: (text) -> (text) query;
toJSONString: (text) -> (text) query;
toString: (text) -> (text) query;
toTimeString: (text) -> (text) query;
toUtcString: (text) -> (text) query;
now: () -> (nat64) query;
parse: (text) -> (nat64) query;
utc: (nat32, nat32) -> (nat64) query;
}
2 changes: 1 addition & 1 deletion examples/date/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export default Canister({
toISOString: query([text], text, (isoString) => {
return new Date(isoString).toISOString();
}),
toJSON: query([text], text, (isoString) => {
toJSONString: query([text], text, (isoString) => {
return new Date(isoString).toJSON();
}),
toString: query([text], text, (isoString) => {
Expand Down
4 changes: 3 additions & 1 deletion examples/date/test/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,9 @@ export function getTests(dateCanister: ActorSubclass<_SERVICE>): Test[] {
test: async () => {
const date = new Date();

const result = await dateCanister.toJSON(date.toISOString());
const result = await dateCanister.toJSONString(
date.toISOString()
);
const expected = date.toJSON();

return {
Expand Down
10 changes: 5 additions & 5 deletions examples/guard_functions/src/index.did
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
service: () -> {
callExpressionWithEmptyOptionsObject: () -> (bool) query;
callExpressionWithoutOptionsObject: () -> (bool) query;
customErrorGuarded: () -> (bool) query;
errorStringGuarded: () -> (bool) query;
getCounter: () -> (nat32) query;
identifierAnnotation: () -> (bool) query;
callExpressionWithoutOptionsObject: () -> (bool) query;
callExpressionWithEmptyOptionsObject: () -> (bool) query;
looselyGuarded: () -> (bool) query;
looselyGuardedManual: () -> (bool) query;
looselyGuardedWithGuardOptionKeyAsString: () -> (bool) query;
modifyStateGuarded: () -> (bool);
tightlyGuarded: () -> (bool) query;
errorStringGuarded: () -> (bool) query;
customErrorGuarded: () -> (bool) query;
nonStringErrValueGuarded: () -> (bool) query;
tightlyGuarded: () -> (bool) query;
}
97 changes: 37 additions & 60 deletions examples/robust_imports/src/index.did
Original file line number Diff line number Diff line change
@@ -1,70 +1,47 @@
type rec_0 = variant {String:text; Thing:int8};
type rec_1 = variant {Thing:int8};
type rec_2 = variant {MyInt16:int16; MyInt8:int8};
type rec_3 = variant {sixteen; eight};
type rec_6 = record {int1:int16; int2:int16; int3:int16; int4:int8; int5:int8; int6:int8; int7:int8; int8:int8; int9:int16};
type rec_7 = record {mytext:text};
type rec_5 = record {type_name:text; name:text; count:int8; greeting:opt text};
type rec_4 = record {myRecord:rec_6; myDeepTuple:record {text}; myCavernousTuple:record {text}; fathomlessRecord:rec_7; coveredRecord:rec_5; myTuple:record {text}};
type rec_9 = variant {Seeds; Seedless};
type rec_10 = record {int:int; starInt:int; int8:int8; int16:int16; int32:int32; int64:int64};
type rec_11 = record {nat:nat; starNat:nat; nat8:nat8; nat16:nat16; nat32:nat32; nat64:nat64};
type rec_12 = record {star:bool};
type rec_13 = record {star:bool};
type rec_14 = record {fifth:int; first:int; tenth:nat; third:float64; eighth:int; seventh:float64; second:int; sixth:float32; ninth:int8; eleventh:nat8; twelfth:float64; fourth:int};
type rec_17 = variant {bad; good; ugly};
type rec_16 = record {depth:nat8};
type rec_15 = record {id:nat; list:vec nat16; name:opt text; tups:record {text; float64}; description:rec_17; depth:rec_16};
type rec_20 = variant {bad; good; ugly};
type rec_19 = record {depth:nat8};
type rec_18 = record {id:nat; list:vec nat16; name:opt text; tups:record {text; float64}; description:rec_20; depth:rec_19};
type rec_23 = variant {bad; good; ugly};
type rec_22 = record {depth:nat8};
type rec_21 = record {id:nat; list:vec nat16; name:opt text; tups:record {text; float64}; description:rec_23; depth:rec_22};
service: () -> {
myVariantToMyDeepVariant: (rec_0) -> (rec_1) query;
myFathomlessVariantToMyCavernousVariant: (rec_2) -> (rec_3) query;
returnVec: () -> (vec vec nat8) query;
returnFathomlessVec: () -> (vec int16) query;
returnWeird: () -> (int64) query;
returnFathomlessCanister: (service {query1:() -> (bool) query; update1:() -> (text) }) -> (service {query1:() -> (bool) query; update1:() -> (text) }) query;
makeCavernousRecord: () -> (rec_4) query;
typeCheck: (vec opt nat16) -> (int16) query;
addSigFigs: (float32) -> (float64) query;
checkCanister: (service {deliver:() -> (text) ; is_delivered:() -> (bool) query}) -> (service {deliver:() -> (text) ; is_delivered:() -> (bool) query}) query;
checkWatermelonForSeeds: (bool, rec_9) -> () query;
compareApplesToOranges: (rec_10, rec_11) -> (bool) query;
handleFarkleberries: (func (text) -> () oneway, func (text) -> (text) query, func (text) -> (text) ) -> (record {func (text) -> (text) ; func (text) -> () oneway; func (text) -> (text) query}) query;
getManagementPeach: () -> (principal) query;
pitOlives: (opt bool) -> (bool) query;
peelBanana: (vec nat8) -> (nat8) query;
putTheCoconutInTheLime: (int16) -> (vec int16) query;
isMangoTrickyToEat: () -> (bool) query;
isFruitPrepared: () -> (bool) query;
removeRambutanSkins: () -> (reserved);
checkCanister: (service {deliver: () -> (text); is_delivered: () -> (bool) query;}) -> (service {deliver: () -> (text); is_delivered: () -> (bool) query;}) query;
checkCanisterAlias: (service {testQuery: () -> (text) query;}) -> (service {testQuery: () -> (text) query;}) query;
checkPrimAliases: (bool, null, text, int, float64) -> () query;
checkWatermelonForSeeds: (bool, variant {Seeds; Seedless}) -> () query;
compareApplesToOranges: (record {"int":int; starInt:int; "int8":int8; "int16":int16; "int32":int32; "int64":int64}, record {"nat":nat; starNat:nat; "nat8":nat8; "nat16":nat16; "nat32":nat32; "nat64":nat64}) -> (bool) query;
compareStars: (record {star:bool}, record {star:bool}) -> (variant {Ok:bool; Err:text}) query;
deepEmptyAlias: () -> (empty) query;
dirtyIlama: () -> ();
pickElderberry: () -> (empty);
compareStars: (rec_12, rec_13) -> (variant {Ok:bool; Err:text}) query;
helloTextAlias: () -> (text) query;
getDeepBlob: (vec nat8) -> (vec nat8) query;
getManagementPeach: () -> (principal) query;
getManualAlias: () -> (float64) query;
getMyRecord: () -> (record {id:nat; list:vec nat16; name:opt text; tups:record {text; float64}; description:variant {bad; good; ugly}; depth:record {depth:nat8}}) query;
getMyRecordAlias: () -> (record {id:nat; list:vec nat16; name:opt text; tups:record {text; float64}; description:variant {bad; good; ugly}; depth:record {depth:nat8}}) query;
getNumberAliases: () -> (record {fifth:int; first:int; tenth:nat; third:float64; eighth:int; seventh:float64; second:int; sixth:float32; ninth:int8; eleventh:nat8; twelfth:float64; fourth:int}) query;
getReservedAlias: () -> (reserved) query;
getStable: (nat16) -> (opt text) query;
getSuperAlias: () -> (record {id:nat; list:vec nat16; name:opt text; tups:record {text; float64}; description:variant {bad; good; ugly}; depth:record {depth:nat8}}) query;
handleFarkleberries: (func (text) -> () oneway, func (text) -> (text) query, func (text) -> (text)) -> (record {func (text) -> (text); func (text) -> () oneway; func (text) -> (text) query}) query;
helloAzleTextAlias: () -> (text) query;
helloMixedTextAlias: () -> (text) query;
helloDeepTextAlias: () -> (text) query;
helloMixedTextAlias: () -> (text) query;
helloStirredTextAlias: () -> (text) query;
getDeepBlob: (vec nat8) -> (vec nat8) query;
deepEmptyAlias: () -> (empty) query;
getNumberAliases: () -> (rec_14) query;
helloTextAlias: () -> (text) query;
isFruitPrepared: () -> (bool) query;
isMangoTrickyToEat: () -> (bool) query;
makeCavernousRecord: () -> (record {myRecord:record {int1:int16; int2:int16; int3:int16; int4:int8; int5:int8; int6:int8; int7:int8; "int8":int8; int9:int16}; myDeepTuple:record {text}; myCavernousTuple:record {text}; fathomlessRecord:record {mytext:text}; coveredRecord:record {type_name:text; name:text; count:int8; greeting:opt text}; myTuple:record {text}}) query;
myFathomlessVariantToMyCavernousVariant: (variant {MyInt16:int16; MyInt8:int8}) -> (variant {sixteen; eight}) query;
myVariantToMyDeepVariant: (variant {String:text; Thing:int8}) -> (variant {Thing:int8}) query;
passPrincipal: (principal) -> (principal) query;
getReservedAlias: () -> (reserved) query;
simpleDeepQuery: () -> () query;
simpleAzleQuery: () -> () query;
simpleQuery: () -> () query;
checkCanisterAlias: (service {testQuery:() -> (text) query}) -> (service {testQuery:() -> (text) query}) query;
getMyRecord: () -> (rec_15) query;
getMyRecordAlias: () -> (rec_18) query;
getSuperAlias: () -> (rec_21) query;
getManualAlias: () -> (float64) query;
peelBanana: (vec nat8) -> (nat8) query;
pickElderberry: () -> (empty);
pitOlives: (opt bool) -> (bool) query;
putTheCoconutInTheLime: (int16) -> (vec int16) query;
removeRambutanSkins: () -> (reserved);
returnFathomlessCanister: (service {query1: () -> (bool) query; update1: () -> (text);}) -> (service {query1: () -> (bool) query; update1: () -> (text);}) query;
returnFathomlessVec: () -> (vec int16) query;
returnFuncAlias: (func (text) -> (text) query) -> (func (text) -> (text) query) query;
returnVec: () -> (vec vec nat8) query;
returnWeird: () -> (int64) query;
setStable: (nat16, text) -> (opt text);
getStable: (nat16) -> (opt text) query;
checkPrimAliases: (bool, null, text, int, float64) -> () query;
simpleAzleQuery: () -> () query;
simpleDeepQuery: () -> () query;
simpleQuery: () -> () query;
typeCheck: (vec opt nat16) -> (int16) query;
}
14 changes: 7 additions & 7 deletions src/compiler/generate_candid_and_canister_methods.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { CanisterMethods } from './utils/types';
import {
DEFAULT_VISITOR_DATA,
didResultToCandidString,
getDefaultVisitorData,
DidVisitor
} from '../lib/candid/did_visitor';
} from '../lib/candid/did_file/visitor.ts';
import { toDidString } from '../lib/candid/did_file';

export function generateCandidAndCanisterMethods(mainJs: string): {
candid: string;
Expand Down Expand Up @@ -36,14 +36,14 @@ export function generateCandidAndCanisterMethods(mainJs: string): {

const canisterMethods = (sandbox.exports as any).canisterMethods;

const candidInfo = canisterMethods.getIDL([]).accept(new DidVisitor(), {
...DEFAULT_VISITOR_DATA,
const candidInfo = canisterMethods.getIdl([]).accept(new DidVisitor(), {
...getDefaultVisitorData(),
isFirstService: true,
systemFuncs: canisterMethods.getSystemFunctionIDLs()
systemFuncs: canisterMethods.getSystemFunctionIdls()
});

return {
candid: didResultToCandidString(candidInfo),
candid: toDidString(candidInfo),
canisterMethods: canisterMethods
};
}
3 changes: 2 additions & 1 deletion src/compiler/rust/canister/src/ic/set_timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ pub fn native_function<'a>(
let global = context.global_object().unwrap();

let timer_callback = global
.get_property("_azleTimerCallbackIds").unwrap()
.get_property("_azleTimerCallbacks")
.unwrap()
.get_property(callback_id.as_str())
.unwrap_or_else(|e| ic_cdk::api::trap(e.to_string().as_str()));

Expand Down
3 changes: 2 additions & 1 deletion src/compiler/rust/canister/src/ic/set_timer_interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ pub fn native_function<'a>(
let global = context.global_object().unwrap();

let timer_callback = global
.get_property("_azleTimerCallbackIds").unwrap()
.get_property("_azleTimerCallbacks")
.unwrap()
.get_property(callback_id.as_str())
.unwrap_or_else(|e| ic_cdk::api::trap(e.to_string().as_str()));

Expand Down
7 changes: 3 additions & 4 deletions src/compiler/rust/canister/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ fn execute_js(function_name: &str, pass_arg_data: bool) {
let exports = global.get_property("exports").unwrap();
let canister_methods = exports.get_property("canisterMethods").unwrap();
let callbacks = canister_methods.get_property("callbacks").unwrap();
let method_callbacks = callbacks.get_property(function_name).unwrap();
let canister_method_callback = method_callbacks.get_property("canisterCallback").unwrap();
let method_callback = callbacks.get_property(function_name).unwrap();

let candid_args = if pass_arg_data {
ic_cdk::api::call::arg_data_raw()
Expand All @@ -94,8 +93,8 @@ fn execute_js(function_name: &str, pass_arg_data: bool) {
let candid_args_js_value_ref = to_qjs_value(&context, &candid_args_js_value).unwrap();

// TODO I am not sure what the first parameter to call is supposed to be
canister_method_callback
.call(&canister_method_callback, &[candid_args_js_value_ref])
method_callback
.call(&method_callback, &[candid_args_js_value_ref])
.unwrap();

context.execute_pending().unwrap();
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/rust/canister_methods/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@ fn get_guard_token_stream(
let context = context.as_mut().unwrap();

let global = context.global_object().unwrap();
let guard_function = global.get_property(#guard_name).unwrap();
let guard_functions = global.get_property("_azleGuardFunctions").unwrap();
let guard_function = guard_functions.get_property(#guard_name).unwrap();

// TODO I am not sure what the first parameter to call is supposed to be
let result = guard_function.call(&guard_function, &[]);
Expand Down
3 changes: 3 additions & 0 deletions src/lib/candid/candid_type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type CandidType = {
_azleCandidType?: '_azleCandidType';
};
1 change: 1 addition & 0 deletions src/lib/candid/did_file/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { toDidString } from './to_did_string';
26 changes: 26 additions & 0 deletions src/lib/candid/did_file/to_did_string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CandidTypesDefs, VisitorResult } from './visitor.ts/index.js';

export function toDidString(result: VisitorResult): string {
// TODO it would be nice to have names for the rec types instead of rec_1, rec_2 etc
// TODO Once types have names we should deduplicate the init and post_upgrade param types
// TODO maybe even before we have names we should deduplicate all sorts of types
// The rust to candid converter we were using did have names, but if two things
// had the same shape they got merged into one type that had one of the names.
// That might not be the ideal situation, but it is the expected behavior in rust

const [candid, candidTypeDefs] = result;
const candidTypesString = newTypeToCandidString(candidTypeDefs);
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
return candidTypesString + candid + '\n';
}

function newTypeToCandidString(newTypes: CandidTypesDefs): string {
return Object.entries(newTypes).length > 0
? newTypesToStingArr(newTypes).join('\n') + '\n'
: '';
}

function newTypesToStingArr(newTypes: CandidTypesDefs): string[] {
return Object.entries(newTypes).map(
([name, candid]) => `type ${name} = ${candid};`
);
}
88 changes: 88 additions & 0 deletions src/lib/candid/did_file/visitor.ts/did_visitor.ts
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { IDL } from '@dfinity/candid';
import { visitService } from './visit_service';
import { visitVariant } from './visit_variant';
import { visitRecord } from './visit_record';
import { visitRecursive } from './visit_recursive';
import { visitPrimitive } from './visit_primitive';
import { visitTuple } from './visit_tuple';
import { visitOpt } from './visit_opt';
import { visitVec } from './visit_vec';
import { visitFunc } from './visit_func';

export type VisitorData = {
usedRecClasses: IDL.RecClass[];
isOnService: boolean;
isFirstService: boolean;
systemFuncs: IDL.FuncClass[];
};
export type VisitorResult = [CandidDef, CandidTypesDefs];

export type TypeName = string;
export type CandidDef = string;
export type CandidTypesDefs = { [key: TypeName]: CandidDef };

export function getDefaultVisitorData(): VisitorData {
return {
usedRecClasses: [],
isOnService: false,
isFirstService: false,
systemFuncs: []
};
}

export class DidVisitor extends IDL.Visitor<VisitorData, VisitorResult> {
visitService(t: IDL.ServiceClass, data: VisitorData): VisitorResult {
return visitService(t, this, data);
}
visitPrimitive<T>(
t: IDL.PrimitiveType<T>,
_data: VisitorData
): VisitorResult {
return visitPrimitive(t);
}
visitTuple<T extends any[]>(
_t: IDL.TupleClass<T>,
components: IDL.Type<any>[],
data: VisitorData
): VisitorResult {
return visitTuple(components, this, data);
}
visitOpt<T>(
_t: IDL.OptClass<T>,
ty: IDL.Type<T>,
data: VisitorData
): VisitorResult {
return visitOpt(ty, this, data);
}
visitVec<T>(
_t: IDL.VecClass<T>,
ty: IDL.Type<T>,
data: VisitorData
): VisitorResult {
return visitVec(ty, this, data);
}
visitFunc(t: IDL.FuncClass, data: VisitorData): VisitorResult {
return visitFunc(t, this, data);
}
visitRec<T>(
t: IDL.RecClass<T>,
ty: IDL.ConstructType<T>,
data: VisitorData
): VisitorResult {
return visitRecursive(t, ty, this, data);
}
visitRecord(
_t: IDL.RecordClass,
fields: [string, IDL.Type<any>][],
data: VisitorData
): VisitorResult {
return visitRecord(fields, this, data);
}
visitVariant(
_t: IDL.VariantClass,
fields: [string, IDL.Type<any>][],
data: VisitorData
): VisitorResult {
return visitVariant(fields, this, data);
}
}
Loading
Loading