From b2c7eeb371924a04346e4dea14a596b3accb9d3c Mon Sep 17 00:00:00 2001 From: mlasson Date: Wed, 27 Aug 2025 18:17:52 +0200 Subject: [PATCH] Experimental support for primitves bindings --- node-test/bindings/expected/fs.ml | 23 ++++++++---- node-test/bindings/expected/imports.ml | 7 +--- node-test/bindings/fs.mli | 2 +- node-test/bindings/imports.js | 9 +++-- node-test/bindings/imports.mli | 5 +-- ppx-lib/gen_js_api_ppx.ml | 52 +++++++++++++++++++------- 6 files changed, 61 insertions(+), 37 deletions(-) diff --git a/node-test/bindings/expected/fs.ml b/node-test/bindings/expected/fs.ml index 8fba8202..232f0faa 100644 --- a/node-test/bindings/expected/fs.ml +++ b/node-test/bindings/expected/fs.ml @@ -93,27 +93,34 @@ let (readdir : string -> string list Promise.t) = fun (x39 : string) -> Promise.t_of_js (fun (x40 : Ojs.t) -> Ojs.list_of_js Ojs.string_of_js x40) - (Ojs.call (Ojs.get_prop_ascii Imports.fs "promises") "readdir" - [|(Ojs.string_to_js x39)|]) + (Ojs.call + (Ojs.get_prop_ascii (Jsoo_runtime.Sys.external_ "node_fs") + "promises") "readdir" [|(Ojs.string_to_js x39)|]) let (open_ : string -> flag:string -> FileHandle.t Promise.t) = fun (x42 : string) -> fun ~flag:(x43 : string) -> Promise.t_of_js FileHandle.t_of_js - (Ojs.call (Ojs.get_prop_ascii Imports.fs "promises") "open" + (Ojs.call + (Ojs.get_prop_ascii (Jsoo_runtime.Sys.external_ "node_fs") + "promises") "open" [|(Ojs.string_to_js x42);(Ojs.string_to_js x43)|]) let (rmdir : string -> unit Promise.t) = fun (x45 : string) -> Promise.t_of_js Ojs.unit_of_js - (Ojs.call (Ojs.get_prop_ascii Imports.fs "promises") "rmdir" - [|(Ojs.string_to_js x45)|]) + (Ojs.call + (Ojs.get_prop_ascii (Jsoo_runtime.Sys.external_ "node_fs") + "promises") "rmdir" [|(Ojs.string_to_js x45)|]) let (rename : string -> string -> unit Promise.t) = fun (x47 : string) -> fun (x48 : string) -> Promise.t_of_js Ojs.unit_of_js - (Ojs.call (Ojs.get_prop_ascii Imports.fs "promises") "rename" + (Ojs.call + (Ojs.get_prop_ascii (Jsoo_runtime.Sys.external_ "node_fs") + "promises") "rename" [|(Ojs.string_to_js x47);(Ojs.string_to_js x48)|]) let (unlink : string -> unit Promise.t) = fun (x50 : string) -> Promise.t_of_js Ojs.unit_of_js - (Ojs.call (Ojs.get_prop_ascii Imports.fs "promises") "unlink" - [|(Ojs.string_to_js x50)|]) + (Ojs.call + (Ojs.get_prop_ascii (Jsoo_runtime.Sys.external_ "node_fs") + "promises") "unlink" [|(Ojs.string_to_js x50)|]) diff --git a/node-test/bindings/expected/imports.ml b/node-test/bindings/expected/imports.ml index ec5d3f67..6421f4fe 100644 --- a/node-test/bindings/expected/imports.ml +++ b/node-test/bindings/expected/imports.ml @@ -1,8 +1,3 @@ [@@@js.dummy "!! This code has been generated by gen_js_api !!"] [@@@ocaml.warning "-7-32-39"] -let (path : Ojs.t) = - Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global "__LIB__NODE__IMPORTS") - "path" -let (fs : Ojs.t) = - Ojs.get_prop_ascii (Ojs.get_prop_ascii Ojs.global "__LIB__NODE__IMPORTS") - "fs" +let (path : Ojs.t) = Jsoo_runtime.Sys.external_ "node_path" diff --git a/node-test/bindings/fs.mli b/node-test/bindings/fs.mli index 67b4b17c..a23fe677 100644 --- a/node-test/bindings/fs.mli +++ b/node-test/bindings/fs.mli @@ -1,4 +1,4 @@ -[@@@js.scope (Imports.fs, "promises")] +[@@@js.scope "@node_fs.promises"] module Dirent : sig type t = Ojs.t diff --git a/node-test/bindings/imports.js b/node-test/bindings/imports.js index 5f63e5a7..904d9516 100644 --- a/node-test/bindings/imports.js +++ b/node-test/bindings/imports.js @@ -1,4 +1,5 @@ -globalThis.__LIB__NODE__IMPORTS = { - path: require('path'), - fs: require('fs'), -}; +//Provides: node_path +var node_path = require('path'); + +//Provides: node_fs +var node_fs = require('fs'); diff --git a/node-test/bindings/imports.mli b/node-test/bindings/imports.mli index 9438019a..cf443b8c 100644 --- a/node-test/bindings/imports.mli +++ b/node-test/bindings/imports.mli @@ -1,4 +1 @@ -[@@@js.scope "__LIB__NODE__IMPORTS"] - -val path: Ojs.t [@@js.global] -val fs: Ojs.t [@@js.global] +val path: Ojs.t [@@js.runtime "node_path"] diff --git a/ppx-lib/gen_js_api_ppx.ml b/ppx-lib/gen_js_api_ppx.ml index 222d5153..8f6aad3a 100644 --- a/ppx-lib/gen_js_api_ppx.ml +++ b/ppx-lib/gen_js_api_ppx.ml @@ -296,6 +296,7 @@ type apply_type = | NewableFunction (* new f(..) *) type valdef = + | Runtime of string | Cast | Ignore | PropGet of string @@ -311,6 +312,7 @@ type valdef = | Auto of valdef let rec string_of_valdef = function + | Runtime _ -> "js.runtime" | Cast -> "js.cast" | Ignore -> "js.ignore" | PropGet _ -> "js.get" @@ -569,6 +571,7 @@ let parse_attr ~global_attrs (s, loc, auto) attribute = in let actions = [ "js.cast", (fun () -> Cast); + "js.runtime", (fun () -> Runtime (opt_name ())); "js.get", (fun () -> PropGet (opt_name ())); "js.set", (fun () -> PropSet (opt_name ~prefix:"set_" ())); "js.index_get", (fun () -> IndexGet); @@ -892,18 +895,31 @@ let ojs_set o s v = else ojs "set_prop" [o; ojs "string_to_js" [str s]; v] +let rec select_split_path o = function + | [] -> assert false + | [x] -> o, x + | x :: xs -> select_split_path (ojs_get o x) xs + let select_path o s = - let rec select_path o = function - | [] -> assert false - | [x] -> o, x - | x :: xs -> select_path (ojs_get o x) xs - in - select_path o (split '.' s) + select_split_path o (split '.' s) let get_path global_object s = let o, x = select_path global_object s in ojs_get o x +let runtime s = + let external_ = Exp.ident (mknoloc (longident_parse "Jsoo_runtime.Sys.external_")) in + match split '.' s with + | s :: tl -> + let root = Exp.apply external_ (nolabel [Exp.constant (Pconst_string (s, Location.none, None))]) in + begin match tl with + | [] -> root + | _ -> + let o, x = select_split_path root tl in + ojs_get o x + end + | [] -> assert false + let ojs_variable s = get_path ojs_global s @@ -1602,15 +1618,20 @@ let global_object ~global_attrs = | hd :: tl -> begin match get_expr_attribute "js.scope" [hd] with | None -> traverse tl - | Some {pexp_desc=Pexp_constant (Pconst_string (prop, _, _)); _} -> ojs_get (traverse tl) prop + | Some {pexp_desc=Pexp_constant (Pconst_string (prop, _, _)); _} -> + if String.length prop > 0 && prop.[0] = '@' then + runtime (String.sub prop 1 (String.length prop - 1)) + else + get_path (traverse tl) prop + | Some {pexp_desc=Pexp_tuple path; _} -> - let init = traverse tl in - let folder state pexp = - match pexp.pexp_desc with - | Pexp_constant (Pconst_string (prop, _, _)) -> ojs_get state prop - | _ -> pexp (* global object *) - in - List.fold_left folder init path + let init = traverse tl in + let folder state pexp = + match pexp.pexp_desc with + | Pexp_constant (Pconst_string (prop, _, _)) -> get_path state prop + | _ -> pexp (* global object *) + in + List.fold_left folder init path | Some global_object -> global_object end in @@ -1908,6 +1929,9 @@ and gen_class_cast = function and gen_def ~global_object loc decl ty = match decl, ty with + | Runtime s, _ -> + js2ml ty (runtime s) + | Cast, Arrow {ty_args = [{lab=Arg; att=_; typ}]; ty_vararg = None; unit_arg = false; ty_res} -> mkfun ~typ (fun this -> js2ml ty_res (ml2js typ this))