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

Dynamic import support #3919

Closed
bobzhang opened this issue Nov 2, 2019 · 11 comments
Closed

Dynamic import support #3919

bobzhang opened this issue Nov 2, 2019 · 11 comments

Comments

@bobzhang
Copy link
Member

bobzhang commented Nov 2, 2019

type xx 

type 'a promise 

external import : 
  'a  -> 
  ('a -> unit) -> 
  unit promise = "bootload" [@@bs.val]
;;  
module type LIST = module type of List  
;;
let _ : _ promise =     
    import (module List :  LIST)(fun (module List) -> 
  Js.log (List.length [1;2]);
  ()
  )

Todo:

  • Have a way to delay the generated requires for List
  • See if we can mitigate the runtime cost
  • Check to see how to ensure invariants enforced by bootload, e.g, it can only load a global module?
@yawaramin
Copy link
Contributor

Is this regarding #2765 ?

@bobzhang
Copy link
Member Author

bobzhang commented Nov 2, 2019

@yawaramin yes, except the proposal here is more type safe?

@yawaramin
Copy link
Contributor

yawaramin commented Nov 2, 2019

@bobzhang your approach here made me think about this a bit more and now I think we can do dynamic imports with just bs.val and bs.as (treating import as just a normal function), here's an example:

(* foo.ml *)
let x = 0

(* import.ml *)
module type FOO = sig
  val x : int
end

external foo : (_ [@bs.as "./foo.bs"]) -> (module FOO) Js.Promise.t =
  "import" [@@bs.val]

let _ = foo |> Js.Promise.then_(fun (module Foo : FOO) ->
  Foo.x |> Js.log |> Js.Promise.resolve)

This generates:

// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE
'use strict';


import("./foo.bs").then((function (Foo) {
        return Promise.resolve((console.log(Foo.x), /* () */0));
      }));

/*  Not a pure module */

[EDIT: this is possible now thanks to the modules-as-objects change! On previous versions this would compile as Foo[/* x */ 0]]

@bloodyowl
Copy link
Collaborator

@bobzhang has there been progress on this? that'd be crucial for overall performance

@sorenhoyer
Copy link

@bobzhang any update? :-)

@tejesh014
Copy link

tejesh014 commented Nov 12, 2020

@yawaramin your solution works fine. Can we make it little more generic, so that it works for any module.

Something like below

module type DyImpConfig = {module type T;};

module Make = (Config: DyImpConfig) => {
  [@bs.val] external importRe: string => Js.Promise.t(module Config.T) = "import";
};

@yawaramin
Copy link
Contributor

@tejesh014 sure, that makes sense. I'll write up an article about it on my blog when I get some time.

@zth
Copy link
Collaborator

zth commented Nov 25, 2020

I'm also interested in whether there has been any recent movement/plans here. 👀

@BlueHotDog
Copy link

Also looking to this

@BlueHotDog
Copy link

hey, any changes here?

@mununki
Copy link
Member

mununki commented Apr 23, 2023

#5703

@mununki mununki closed this as completed Apr 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants