-
Notifications
You must be signed in to change notification settings - Fork 157
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
Compile to javascript and use it as local storage #117
Comments
I also needed to provide JS helpers for:
|
I think |
For Irmin, it is already possible (but maybe not documented well enough) to change the Hash module. It is not yet possible to do it in For instance, if you want a pure in-memory backend, with a custom hash function:
Note: in this case, all of the "basic" API is not available anymore, and the user should use |
@samoht yes, but Irmin still pulls in @dbuenzli thanks - I was looking for a pure OCaml SHA1 and couldn't find one (was using |
This is due to zarith auto-init code ( |
This one works pretty well in JS, https://github.com/imaya/zlib.js although I tool would prefer a zlibm from @dbuenzli :) |
Le mardi, 17 février 2015 à 13:05, Thomas Gazagnaire a écrit :
Unfortunately I just have sketched a non-blocking API so far, implementing Daniel |
@samoht Zarith failure could conceivably be solved by moving |
note that a delflatem doing 0 compression (using level=0) would be more than enough for our needs. @pqwy in that case, need to turn-on the relevant option ( |
Note that using module aliases will lift nocrypto to be 4.02.0+ only. Perhaps it's time to just switch... |
Asking precisely because of 4.02.0+. Planned on doing that, was holding off until a major 4.01.0 deprecation MirageOS-wide. |
every major deprecation starts with one small uprising. Perhaps nocrypto can lead the 4.01 retirement charge. |
Le mardi, 17 février 2015 à 18:45, David Kaloper a écrit :
At a certain point I'm sure we still want to be able to use nocrypto with js_of_ocaml… Daniel |
I managed to get Irmin in the browser almost working (using @talex5's codes as a guide ;)). There is an ugly issue though. The setup I am trying to get working is Irmin_mem store in the browser pulling from Irmin_fs store via XHR requests. Pulling fails because of mismatch between commit hashes calculated by different backends. I tracked issue down to bin_prot serialization of big integers, e.g. dates, uids (in particular integers bigger than 0x7fff, so not really that big ;)). For instance the following code: To be fair js_of_ocaml spits out a bunch of warnings during compilation:
and in this case the incorrect translation of this bin_prot code seems to be the culprit. Not sure what to do with this bug though. Seems to be a bug/limitation of js_of_ocaml, but not easily fixable. Any suggestions? |
Thanks for the report, that's very interesting! Would be interesting to see if you can reproduce your example without As a short-term workaround, you can try to make your own serialisation format for the blob, tree and commits. Something like that might work (ie. adapting module JSON = struct
let to_string t = Ezjsonm.(to_string (wrap t))
let of_string s = Ezjsonm.(unwrap (from_string s))
let write t buf =
let str = to_string t in
let len = String.length str in
Cstruct.blit_from_string str 0 buf 0 len;
Cstruct.shift buf len
let read buf =
Mstruct.get_string buf (Mstruct.length buf)
|> of_string
let size_of t =
let str = to_string t in
String.length str
let make (type t) (module S: Tc.S0 with type t = t):
t Tc.writer * t Tc.reader * t Tc.size_of =
(fun t -> write (S.to_json t)),
(fun b -> S.of_json (read b)),
(fun t -> size_of (S.to_json t))
end
module Make (AO: Irmin.AO_MAKER) (RW: Irmin.RW_MAKER)
(C: Irmin.Contents.S) (T: Irmin.Tag.S) (H: Irmin.Hash.S)
= struct
module X = struct
module Contents = Irmin.Contents.Make (struct
include AO(H)(C)
module Key = H
module Val = struct
include C
let write, read, size_of = JSON.make (module C)
end
end)
module Node = struct
module Key = H
module Val = struct
module X = Irmin.Private.Node.Make (H)(H)(C.Path)
include X
let write, read, size_of = JSON.make (module X)
end
module Path = C.Path
include AO(Key)(Val)
end
module Commit = struct
module Key = H
module Val = struct
module X = Irmin.Private.Commit.Make(H)(H)
include X
let write, read, size_of = JSON.make (module X)
end
include AO (Key)(Val)
end
module Tag = struct
module Key = T
module Val = H
include RW (Key)(Val)
end
module Slice = Irmin.Private.Slice.Make(Contents)(Node)(Commit)
module Sync = Irmin.Private.Sync.None(H)(T)
end
include Irmin.Make_ext(X)
end A longer-term but better fix (but a bit more involved...) would be to use a the Git format instead of bin-prot, which means porting [1] https://github.com/mirage/mirage-tc/blob/master/lib/tc.ml#L670 |
Is there a js_of_ocaml bug upstream about the serialisation at all? |
I don't think it is bin_prot issue at all, because the test case stripped to its essence is simply
I will open an issue on js_of_ocaml tracker but based on the fact that the warning is emitted the issue is known and not easy to deal with. @samoht Thanks! Will try your workaround tomorrow. |
@ztlpn is your code available publicly? I'd like to get remote sync working from the browser too. |
btw the issue of truncated 64b ints has been reported upstream: ocsigen/js_of_ocaml#285 |
@talex5 Not at the moment - the setup is very hackish at the moment (e.g. I had to use an nginx proxy in front of Irmin http server to work around CORS issues) but I plan to clean it up and release a minimal example of js <-> http server sync which would be useful for others. |
Ah, OK. I'm working on adding support to CueKeeper at the moment. I'm using my own server code so that I can host the static files on the same server that stores the repository, and provide a more limited API (just fast-forward push and fetch). |
So, to summarise the bit_prot issue: When writing out an int, On a 32-bit system 0x80000000 is negative, but the test is only present when compiled for a 64-bit target. However, for Javascript we usually compile for 64-bit and then run js_of_ocaml on the 64-bit code, which truncates everything to 32-bit (not sure why; Javascript uses doubles for everything and so should be OK up to about 52 bits). When we ask to write out a smallish int value such as 0x10000 using bin_prot on Javascript, it therefore decides to use the longer 9 byte representation even though 5 bytes would have been fine. When we sync, we send the data as JSON to the server, which then converts it back to binary, but this time choosing the shorter representation, which therefore has a different hash. Presumably, the same problem would happen in reverse when going the other way. Using a 32-bit compiler would avoid the issue, but it's annoying to have to switch compilers when compiling different parts of the application. If the problem is fixed in a later version, we should still be able to load data saved with the longer representation, but we won't be able to sync it (therefore, history must be lost or regenerated when upgrading). |
In JavaScript, bitwise integer ops are 32-bit so, e.g., |
Closing this bug, as the remaining fixes are not part of Irmin. For reference, to use Irmin with js_of_ocaml you need this pin:
This removes the 64-bit optimisations that go wrong when recompiled to 32-bit Javascript. You also need to pass helpers.js on the |
It is theoretically possible to compile Irmin to Javascript but in practice we are not here yet. Most of the C externals which appears in the bytecode are related to https://github.com/mirleft/ocaml-nocrypto. Might be worth looking at https://github.com/evanvosberg/crypto-js for the missing ones.
The text was updated successfully, but these errors were encountered: