ocsigen / js_of_ocaml

Compiler from OCaml to Javascript.
http://ocsigen.org/js_of_ocaml/
Other
961 stars 188 forks source link

Loading additional js_of_ocaml-compiled js files dynamically #450

Closed zoggy closed 8 years ago

zoggy commented 8 years ago

Hello,

Suppose I have a program with a module offering a plugin interface (some register function). I compile this program using js_of_ocaml and make an HTML page load this script. Fine.

Now when I compile a plugin.ml file to plugin.cmo then to plugin.js, I get this error in the browser console when it is loaded: ReferenceError: caml_get_global_data is not defined.

Are there any compilation flags to make this work ? I tried a --no-runtime with no success.

I saw there is some Dynlink support but the --file and pseudo filesystem is not very clear. I made a test: First I compile plugin.ml to plugin.cmo. Then I add a dummy.ml file with:

Dynlink.loadfile "plugin.cmo";;

I compile this file and create a plugin.js file:

ocamlfind ocamlc -c -package js_of_ocaml.ppx dummy.ml
js_of_ocaml -o plugin.js -I ./ --file=plugin.cmo dummy.cmo

Now when loading plugin.js in the test page, I get: ReferenceError: caml_fs_register.

My goal is to be able to fetch cm{o,a} or .js files from urls and load them in my js_of_ocaml-compiled application.

hhugo commented 8 years ago

https://github.com/ocsigen/js_of_ocaml/issues/369

hhugo commented 8 years ago

Dynlink of JavaScript file doesn't work yet.

Dynlink of cmo should work with Dynlink.loadfile "plugin.cmo";; You might have to compile the main program with --toplevel

To solve the ReferenceError: caml_fs_register error, compile you main program with --extern-fs

zoggy commented 8 years ago

Thanks. I did not think about this option since I don't want to create a toplevel.

When compiling with --toplevel I get an error: js_of_ocaml: Error: interface file 'CSS' not found.

zoggy commented 8 years ago

If I add the package js_of_ocaml.toplevel when compiling the main program:

ocamlfind ocamlc -o lib.byte -package js_of_ocaml.ppx,js_of_ocaml.toplevel -linkpkg -linkall lib.ml

Then js_of_ocaml complains with another error message:

$ js_of_ocaml +dynlink.js +toplevel.js --linkall --extern-fs --toplevel lib.byte
js_of_ocaml: Error: interface file 'Ast_helper' not found
hhugo commented 8 years ago

You can use -I dir option to add more path into scope.

js_of_ocaml +dynlink.js +toplevel.js --linkall --extern-fs --toplevel -I `opam config var lib`/ocaml/compiler-libs` lib.byte

With the following commit, js_of_ocaml does not fail anymore in this case and output warnings. https://github.com/ocsigen/js_of_ocaml/commit/25450c73bd98e35113513df88210207e677016da

hhugo commented 8 years ago

@zoggy, is this working for you now ?

zoggy commented 8 years ago

No. I use master branch of js_of_ocaml. Now I also have to give -I directives for each library used and still some seem to be not found:

 js_of_ocaml +dynlink.js +toplevel.js --linkall --extern-fs --toplevel -I `opam config var lib`/ocaml/compiler-libs -I `opam confi var lib`/js_of_ocaml -I `opam config var lib`/lwt -I `opam config var lib`/base64 -I . lib.byte
warning: free variables in primitive code "caml_json" (/home/guesdon/.opam/4.03.0/lib/js_of_ocaml/polyfill/json2.js:522)
vars: TypeError
Some OCaml interface files were not found.
Use [-I dir_of_cmis] option to bring them into scope
  Compiler.Vlq64
  Compiler.VarPrinter
  Compiler.Util
  Compiler.Tailcall
  Compiler.Specialize_js
  Compiler.Specialize
  Compiler.Source_map
  Compiler.Reserved
  Compiler.Pure_fun
  Compiler.PseudoFs
  Compiler.Pretty_print
  Compiler.Phisimpl
  Compiler.Parse_js
  Compiler.Parse_info
  Compiler.Parse_bytecode
  Compiler.Option
  Compiler.Linker
  Compiler.Jsoo_subst
  Compiler.Jsoo_strongly_connected_components
  Compiler.Jsoo_primitive
  Compiler.Jsoo_deadcode
  Compiler.Json
  Compiler.Js_traverse
  Compiler.Js_token
  Compiler.Js_simpl
  Compiler.Js_parser
  Compiler.Js_output
  Compiler.Js_lexer
  Compiler.Js_assign
  Compiler.Javascript
  Compiler.Instr
  Compiler.Inline
  Compiler.Generate_closure
  Compiler.Generate
  Compiler.Freevars
  Compiler.Flow
  Compiler.Eval
  Compiler.Driver
  Compiler.Dgraph
  Compiler.Compiler_version
  Compiler.Code
  Compiler.Annot_parser
  Compiler.Annot_lexer
There are some missing primitives
Dummy implementations (raising 'Failure' exception) will be used if they are not available at runtime.
You can prevent the generation of dummy implementations with the commandline option '--disable genprim'
Missing primitives:
  caml_ephe_blit_data
  caml_ephe_blit_key
  caml_ephe_check_data
  caml_ephe_check_key
  caml_ephe_create
  caml_ephe_get_data
  caml_ephe_get_data_copy
  caml_ephe_get_key
  caml_ephe_get_key_copy
  caml_ephe_set_data
  caml_ephe_set_key
  caml_ephe_unset_data
  caml_ephe_unset_key

But when loading the plugin code I get:

plugin.js:529 >> Fatal error: Toplevel bytecode executable is corrupted
plugin.js:2693 Uncaught 248,Misc.Fatal_error,11

I just setup a git repo with my test: https://github.com/zoggy/jsoo-dynload-test . Just run sh compile.sh and try browsing the test.html file.

hhugo commented 8 years ago

fixed with https://github.com/zoggy/jsoo-dynload-test/pull/1 Note that you have to use https://github.com/ocsigen/js_of_ocaml/pull/480

hhugo commented 8 years ago

done