diff --git a/default.nix b/default.nix index 5ede45f76fb..d5e1d099368 100644 --- a/default.nix +++ b/default.nix @@ -36,6 +36,17 @@ let dfinity-repo = import (builtins.fetchGit { rev = "ab9d9d6ccba33748fc92f6e8d631327f7f25aead"; }) { system = nixpkgs.system; }; in +let sdk = import (builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/sdk"; + ref = "paulyoung/ts-user-library"; + rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; +}) { system = nixpkgs.system; }; in + +let esm = builtins.fetchTarball { + sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; + url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; +}; in + let real-dvm = if dvm == null then dev.dvm @@ -46,8 +57,7 @@ let real-drun = then dfinity-repo.dfinity.drun else drun; in -# Include js-client -let js-client = dev.js-dfinity-client; in +let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { overrides = self: super: { @@ -269,11 +279,12 @@ rec { nixpkgs.getconf nixpkgs.nodejs-10_x filecheck - js-client + js-user-library dvm drun qc-actorscript lsp-int + esm ] ++ llvmBuildInputs; @@ -283,7 +294,8 @@ rec { export ASC=asc export AS_LD=as-ld export DIDC=didc - export JSCLIENT=${js-client} + export ESM=${esm} + export JS_USER_LIBRARY=${js-user-library} asc --version make parallel qc-actorscript${nixpkgs.lib.optionalString (replay != 0) @@ -552,8 +564,9 @@ rec { )); shellHook = llvmEnv; + ESM=esm; + JS_USER_LIBRARY=js-user-library; TOMMATHSRC = libtommath; - JSCLIENT = js-client; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; } else null; diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index ff0f5d8ed34..1e159436d64 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -108,7 +108,7 @@ let rec pp_typ ppf t = | OptT t -> str ppf "IDL.Opt("; pp_typ ppf t; str ppf ")"; | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field "," ts; str ppf "})"; | FuncT (ms, t1, t2) -> - str ppf "IDL.Message("; + str ppf "IDL.Func("; pp_fields ppf t1; kwd ppf ","; pp_fields ppf t2; @@ -169,28 +169,40 @@ let pp_rec ppf x = pp_close_box ppf (); pp_print_cut ppf () -let pp_actor ppf actor = +let pp_actor ppf actor recs = pp_open_hovbox ppf 1; kwd ppf "const"; (match actor.it with | ActorD (x, t) -> let x = ("actor_" ^ x.it) @@ x.at in - match t.it with - | ServT tp -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth "," tp; - str ppf "})" - | VarT var -> id ppf x; space ppf (); kwd ppf "="; id ppf var - | _ -> assert false + (match t.it with + | ServT tp -> + id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth "," tp; + str ppf "});" + | VarT var -> + id ppf x; space ppf (); kwd ppf "="; + if TS.mem var.it recs then + str ppf (var.it ^ ".__typ;") + else + str ppf var.it; + | _ -> assert false + ); + pp_force_newline ppf (); + kwd ppf "return"; id ppf x; str ppf ";" ); pp_close_box ppf () let pp_header ppf () = pp_open_vbox ppf 0; - str ppf "const IDL = require('IDL')"; + str ppf "export default ({ IDL }) => {"; pp_close_box ppf () - + +let pp_footer ppf () = + pp_force_newline ppf (); + pp_print_string ppf "};" + let pp_prog ppf env prog = match prog.it.actor with | None -> () @@ -205,8 +217,9 @@ let pp_prog ppf env prog = pp_open_vbox ppf 0; TS.iter (pp_rec ppf) recs; List.iter (pp_dec ppf) env_list; - pp_actor ppf actor; - pp_close_box ppf () + pp_actor ppf actor recs; + pp_close_box ppf (); + pp_footer ppf () let compile (scope : Typing.scope) (prog : Syntax.prog) = let buf = Buffer.create 100 in diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 2225b3b1fd9..36fbe4a2d93 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,9 +1,11 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const o = IDL.Rec() -const f = IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) -const h = IDL.Message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) +const f = IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) +const h = IDL.Func(IDL.Obj({'0': f}), IDL.Obj({'0': f})) const g = f o.fill(IDL.Opt(o)) const actor_g = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, - 'h': g, 'o': IDL.Message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) + 'f': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, 'h': g, + 'o': IDL.Func(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}); + return actor_g; +}; diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index f04f438c3ba..6aaa361324b 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const A = IDL.Rec() const C = A const B = IDL.Opt(C) @@ -8,5 +8,7 @@ const Y = Z const X = Y const actor_S = new IDL.ActorInterface({ 'f': - IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), - IDL.Obj({}))}) + IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), + IDL.Obj({}))}); + return actor_S; +}; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 360efbdc716..0570db603c6 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,7 +1,10 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const t = IDL.Nat const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) const actor_S = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) + 'f': IDL.Func(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}); + + return actor_S; +}; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 4e2493fcfad..00c249c0f3c 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, @@ -15,5 +15,7 @@ const nest_record = '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) const actor_S = new IDL.ActorInterface({ 'f': - IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), - IDL.Obj({}))}) + IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({})) + }); + return actor_S; +}; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index fa9377df38d..daef8d6b5e0 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat @@ -13,7 +13,10 @@ const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const actor_S = new IDL.ActorInterface({ 'f': - IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), + IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({'0': list, '1': IdErr})), 'getInventory': - IDL.Message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) + IDL.Func(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}); + + return actor_S; +}; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index 23a298b9391..944ff4a8b2b 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,7 +1,9 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat const t2 = UserId const actor_S = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) + 'f': IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}); + return actor_S; +}; diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index 517f9849fb4..fbd7f269d06 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,16 +1,16 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -21,6 +21,8 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.Message(IDL.Obj({'0': list}), - IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const actor_S = s + IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) + })) +const actor_S = s.__typ; + return actor_S; +}; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index 436f404354e..970e4d46cb8 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,5 +1,7 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const actor_num = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), - 'g': IDL.Message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), - 'h': IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) + 'f': IDL.Func(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), + 'g': IDL.Func(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), + 'h': IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}); + return actor_num; +}; diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 06ea8d3f87f..25173a75769 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const UserId = IDL.Nat const RegionId = IDL.Nat const ProducerId = IDL.Nat @@ -14,5 +14,7 @@ const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const actor_ProduceExchange = new IDL.ActorInterface({ 'getInventory': - IDL.Message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), - IDL.Obj({'0': Inventory, '1': IdErr}))}) + IDL.Func(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), + IDL.Obj({'0': Inventory, '1': IdErr}))}); + return actor_ProduceExchange; +}; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 1b71a15819f..5d828a96773 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,16 +1,16 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -21,6 +21,8 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.Message(IDL.Obj({'0': list}), - IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const actor_A = s + IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) + })) +const actor_A = s.__typ; + return actor_A; +}; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index dc13ef34670..178c3c7ff66 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,23 +1,24 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const my_type = IDL.Nat const B = my_type const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': - IDL.Message(IDL.Obj({'name': IDL.Text}), + IDL.Func(IDL.Obj({'name': IDL.Text}), IDL.Obj({ '0': - new IDL.ActorInterface({'up': IDL.Message(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.Message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) + new IDL.ActorInterface({'up': IDL.Func(IDL.Obj({}), IDL.Obj({})), + 'current': IDL.Func(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) const actor_server = new IDL.ActorInterface({ 'addUser': - IDL.Message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), + IDL.Func(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), IDL.Obj({'id': IDL.Nat64})), - 'userName': - IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), - 'f': IDL.Message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) + 'userName': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), + 'deleteUser': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), + 'f': IDL.Func(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}); + return actor_server; +}; diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index f8f246b20ae..8c6ac0b1ec6 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const A = IDL.Obj({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat}) @@ -6,7 +6,9 @@ const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) const actor_C = new IDL.ActorInterface({ - '函数名': IDL.Message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '👀': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '✈️ 🚗 ⛱️ ': IDL.Message(IDL.Obj({}), IDL.Obj({}))}) + '函数名': IDL.Func(IDL.Obj({'0': A}), IDL.Obj({'0': B})), + '': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '👀': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '✈️ 🚗 ⛱️ ': IDL.Func(IDL.Obj({}), IDL.Obj({}))}); + return actor_C; +}; diff --git a/test/run.sh b/test/run.sh index 5c4373816ed..edab391f9ae 100755 --- a/test/run.sh +++ b/test/run.sh @@ -31,7 +31,6 @@ export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) -JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} ECHO=echo while getopts "a12sir" o; do @@ -274,10 +273,18 @@ do if [ -e $out/$base.js ] then $ECHO -n " [node]" - export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src - node $out/$base.js >& $out/$base.node 2>&1 + export NODE_PATH=$NODE_PATH:$ESM + + node -r esm $out/$base.js > $out/$base.node 2>&1 normalize $out/$base.node diff_files="$diff_files $base.node" + + node -r esm -e \ + "import actorInterface from './$out/$base.js'; + import { makeActor, makeHttpAgent } from '$JS_USER_LIBRARY'; + const httpAgent = makeHttpAgent({ canisterId: 1 }); + const actor = makeActor(actorInterface)(httpAgent); + assert(Object.entries(actor).length > 0);" fi fi fi